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"
67 static const char *arg_type = NULL;
68 static const char *arg_load_state = NULL;
69 static char **arg_property = NULL;
70 static bool arg_all = false;
71 static const char *arg_job_mode = "replace";
72 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
73 static bool arg_no_block = false;
74 static bool arg_no_legend = false;
75 static bool arg_no_pager = false;
76 static bool arg_no_wtmp = false;
77 static bool arg_no_sync = 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 bool error_is_no_service(const DBusError *error) {
208 if (!dbus_error_is_set(error))
211 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
214 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
217 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
220 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
223 if (!dbus_error_is_set(error))
226 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
227 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
228 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
229 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
230 return EXIT_NOPERMISSION;
232 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
233 return EXIT_NOTINSTALLED;
235 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
236 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
237 return EXIT_NOTIMPLEMENTED;
239 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
240 return EXIT_NOTCONFIGURED;
248 static int bus_method_call_with_reply(DBusConnection *bus,
249 const char *destination,
251 const char *interface,
253 DBusMessage **return_reply,
254 DBusError *return_error,
255 int first_arg_type, ...) {
257 DBusMessage *m, *reply;
261 dbus_error_init(&error);
264 m = dbus_message_new_method_call(destination, path, interface, method);
270 va_start(ap, first_arg_type);
271 if (!dbus_message_append_args_valist(m, first_arg_type, ap)) {
273 dbus_message_unref(m);
279 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
280 dbus_message_unref(m);
282 log_error("Failed to issue method call: %s", bus_error_message(&error));
283 if (error_is_no_service(&error))
285 else if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED))
287 else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
294 *return_reply = reply;
296 dbus_message_unref(reply);
301 dbus_error_free(&error);
306 static void warn_wall(enum action a) {
307 static const char *table[_ACTION_MAX] = {
308 [ACTION_HALT] = "The system is going down for system halt NOW!",
309 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
310 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
311 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
312 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
313 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
314 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
323 p = strv_join(arg_wall, " ");
325 log_error("Failed to join strings.");
341 utmp_wall(table[a], NULL);
344 static bool avoid_bus(void) {
346 if (running_in_chroot() > 0)
349 if (sd_booted() <= 0)
352 if (!isempty(arg_root))
355 if (arg_scope == UNIT_FILE_GLOBAL)
363 const char *description;
364 const char *load_state;
365 const char *active_state;
366 const char *sub_state;
367 const char *following;
368 const char *unit_path;
370 const char *job_type;
371 const char *job_path;
374 static int compare_unit_info(const void *a, const void *b) {
376 const struct unit_info *u = a, *v = b;
378 d1 = strrchr(u->id, '.');
379 d2 = strrchr(v->id, '.');
384 if ((r = strcasecmp(d1, d2)) != 0)
388 return strcasecmp(u->id, v->id);
391 static bool output_show_unit(const struct unit_info *u) {
395 return streq(u->active_state, "failed");
397 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
398 streq(dot+1, arg_type))) &&
399 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
400 (arg_all || !(streq(u->active_state, "inactive")
401 || u->following[0]) || u->job_id > 0);
404 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
405 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
406 const struct unit_info *u;
408 max_id_len = sizeof("UNIT")-1;
409 active_len = sizeof("ACTIVE")-1;
410 sub_len = sizeof("SUB")-1;
411 job_len = sizeof("JOB")-1;
414 for (u = unit_infos; u < unit_infos + c; u++) {
415 if (!output_show_unit(u))
418 max_id_len = MAX(max_id_len, strlen(u->id));
419 active_len = MAX(active_len, strlen(u->active_state));
420 sub_len = MAX(sub_len, strlen(u->sub_state));
422 job_len = MAX(job_len, strlen(u->job_type));
427 id_len = MIN(max_id_len, 25);
428 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
429 if (basic_len < (unsigned) columns()) {
430 unsigned extra_len, incr;
431 extra_len = columns() - basic_len;
432 /* Either UNIT already got 25, or is fully satisfied.
433 * Grant up to 25 to DESC now. */
434 incr = MIN(extra_len, 25);
437 /* split the remaining space between UNIT and DESC,
438 * but do not give UNIT more than it needs. */
440 incr = MIN(extra_len / 2, max_id_len - id_len);
442 desc_len += extra_len - incr;
448 if (!arg_no_legend) {
449 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
450 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
451 if (!arg_full && arg_no_pager)
452 printf("%.*s\n", desc_len, "DESCRIPTION");
454 printf("%s\n", "DESCRIPTION");
457 for (u = unit_infos; u < unit_infos + c; u++) {
459 const char *on_loaded, *off_loaded;
460 const char *on_active, *off_active;
462 if (!output_show_unit(u))
467 if (streq(u->load_state, "error")) {
468 on_loaded = ansi_highlight_red(true);
469 off_loaded = ansi_highlight_red(false);
471 on_loaded = off_loaded = "";
473 if (streq(u->active_state, "failed")) {
474 on_active = ansi_highlight_red(true);
475 off_active = ansi_highlight_red(false);
477 on_active = off_active = "";
479 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
481 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
482 id_len, e ? e : u->id,
483 on_loaded, u->load_state, off_loaded,
484 on_active, active_len, u->active_state,
485 sub_len, u->sub_state, off_active,
486 job_len, u->job_id ? u->job_type : "");
487 if (!arg_full && arg_no_pager)
488 printf("%.*s\n", desc_len, u->description);
490 printf("%s\n", u->description);
495 if (!arg_no_legend) {
496 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
497 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
498 "SUB = The low-level unit activation state, values depend on unit type.\n"
499 "JOB = Pending job for the unit.\n");
502 printf("\n%u units listed.\n", n_shown);
504 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
508 static int list_units(DBusConnection *bus, char **args) {
509 DBusMessage *reply = NULL;
511 DBusMessageIter iter, sub, sub2;
512 unsigned c = 0, n_units = 0;
513 struct unit_info *unit_infos = NULL;
515 pager_open_if_enabled();
517 r = bus_method_call_with_reply (
519 "org.freedesktop.systemd1",
520 "/org/freedesktop/systemd1",
521 "org.freedesktop.systemd1.Manager",
529 if (!dbus_message_iter_init(reply, &iter) ||
530 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
531 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
532 log_error("Failed to parse reply.");
537 dbus_message_iter_recurse(&iter, &sub);
539 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
542 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
543 log_error("Failed to parse reply.");
551 n_units = MAX(2*c, 16);
552 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
555 log_error("Failed to allocate unit array.");
565 dbus_message_iter_recurse(&sub, &sub2);
567 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
568 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
569 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
570 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
571 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
572 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
573 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
574 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
575 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
576 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
577 log_error("Failed to parse reply.");
582 dbus_message_iter_next(&sub);
587 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
588 output_units_list(unit_infos, c);
593 dbus_message_unref(reply);
600 static int compare_unit_file_list(const void *a, const void *b) {
602 const UnitFileList *u = a, *v = b;
604 d1 = strrchr(u->path, '.');
605 d2 = strrchr(v->path, '.');
610 r = strcasecmp(d1, d2);
615 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
618 static bool output_show_unit_file(const UnitFileList *u) {
621 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
624 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
625 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
626 const UnitFileList *u;
628 max_id_len = sizeof("UNIT FILE")-1;
629 state_cols = sizeof("STATE")-1;
630 for (u = units; u < units + c; u++) {
631 if (!output_show_unit_file(u))
634 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
635 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
640 id_cols = MIN(max_id_len, 25);
641 basic_cols = 1 + id_cols + state_cols;
642 if (basic_cols < (unsigned) columns())
643 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
645 id_cols = max_id_len;
648 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
650 for (u = units; u < units + c; u++) {
652 const char *on, *off;
655 if (!output_show_unit_file(u))
660 if (u->state == UNIT_FILE_MASKED ||
661 u->state == UNIT_FILE_MASKED_RUNTIME ||
662 u->state == UNIT_FILE_DISABLED) {
663 on = ansi_highlight_red(true);
664 off = ansi_highlight_red(false);
665 } else if (u->state == UNIT_FILE_ENABLED) {
666 on = ansi_highlight_green(true);
667 off = ansi_highlight_green(false);
671 id = path_get_file_name(u->path);
673 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
675 printf("%-*s %s%-*s%s\n",
677 on, state_cols, unit_file_state_to_string(u->state), off);
683 printf("\n%u unit files listed.\n", n_shown);
686 static int list_unit_files(DBusConnection *bus, char **args) {
687 DBusMessage *reply = NULL;
689 DBusMessageIter iter, sub, sub2;
690 unsigned c = 0, n_units = 0;
691 UnitFileList *units = NULL;
693 pager_open_if_enabled();
700 h = hashmap_new(string_hash_func, string_compare_func);
704 r = unit_file_get_list(arg_scope, arg_root, h);
706 unit_file_list_free(h);
707 log_error("Failed to get unit file list: %s", strerror(-r));
711 n_units = hashmap_size(h);
712 units = new(UnitFileList, n_units);
714 unit_file_list_free(h);
718 HASHMAP_FOREACH(u, h, i) {
719 memcpy(units + c++, u, sizeof(UnitFileList));
725 r = bus_method_call_with_reply (
727 "org.freedesktop.systemd1",
728 "/org/freedesktop/systemd1",
729 "org.freedesktop.systemd1.Manager",
737 if (!dbus_message_iter_init(reply, &iter) ||
738 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
739 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
740 log_error("Failed to parse reply.");
745 dbus_message_iter_recurse(&iter, &sub);
747 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
751 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
752 log_error("Failed to parse reply.");
760 n_units = MAX(2*c, 16);
761 w = realloc(units, sizeof(struct UnitFileList) * n_units);
764 log_error("Failed to allocate unit array.");
774 dbus_message_iter_recurse(&sub, &sub2);
776 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
777 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
778 log_error("Failed to parse reply.");
783 u->state = unit_file_state_from_string(state);
785 dbus_message_iter_next(&sub);
791 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
792 output_unit_file_list(units, c);
799 dbus_message_unref(reply);
806 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
807 static const char * const colors[] = {
808 "Requires", "[color=\"black\"]",
809 "RequiresOverridable", "[color=\"black\"]",
810 "Requisite", "[color=\"darkblue\"]",
811 "RequisiteOverridable", "[color=\"darkblue\"]",
812 "Wants", "[color=\"grey66\"]",
813 "Conflicts", "[color=\"red\"]",
814 "ConflictedBy", "[color=\"red\"]",
815 "After", "[color=\"green\"]"
818 const char *c = NULL;
825 for (i = 0; i < ELEMENTSOF(colors); i += 2)
826 if (streq(colors[i], prop)) {
834 if (arg_dot != DOT_ALL)
835 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
838 switch (dbus_message_iter_get_arg_type(iter)) {
840 case DBUS_TYPE_ARRAY:
842 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
845 dbus_message_iter_recurse(iter, &sub);
847 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
850 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
851 dbus_message_iter_get_basic(&sub, &s);
852 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
854 dbus_message_iter_next(&sub);
864 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
865 DBusMessage *reply = NULL;
866 const char *interface = "org.freedesktop.systemd1.Unit";
868 DBusMessageIter iter, sub, sub2, sub3;
872 r = bus_method_call_with_reply (
874 "org.freedesktop.systemd1",
876 "org.freedesktop.DBus.Properties",
880 DBUS_TYPE_STRING, &interface,
885 if (!dbus_message_iter_init(reply, &iter) ||
886 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
887 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
888 log_error("Failed to parse reply.");
893 dbus_message_iter_recurse(&iter, &sub);
895 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
898 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
899 log_error("Failed to parse reply.");
904 dbus_message_iter_recurse(&sub, &sub2);
906 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
907 log_error("Failed to parse reply.");
912 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
913 log_error("Failed to parse reply.");
918 dbus_message_iter_recurse(&sub2, &sub3);
920 if (dot_one_property(name, prop, &sub3)) {
921 log_error("Failed to parse reply.");
926 dbus_message_iter_next(&sub);
931 dbus_message_unref(reply);
936 static int dot(DBusConnection *bus, char **args) {
937 DBusMessage *reply = NULL;
939 DBusMessageIter iter, sub, sub2;
941 r = bus_method_call_with_reply (
943 "org.freedesktop.systemd1",
944 "/org/freedesktop/systemd1",
945 "org.freedesktop.systemd1.Manager",
953 if (!dbus_message_iter_init(reply, &iter) ||
954 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
955 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
956 log_error("Failed to parse reply.");
961 printf("digraph systemd {\n");
963 dbus_message_iter_recurse(&iter, &sub);
964 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
965 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
967 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
968 log_error("Failed to parse reply.");
973 dbus_message_iter_recurse(&sub, &sub2);
975 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
976 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
980 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
981 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
982 log_error("Failed to parse reply.");
987 if ((r = dot_one(bus, id, unit_path)) < 0)
990 /* printf("\t\"%s\";\n", id); */
991 dbus_message_iter_next(&sub);
996 log_info(" Color legend: black = Requires\n"
997 " dark blue = Requisite\n"
998 " dark grey = Wants\n"
1000 " green = After\n");
1003 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1004 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1010 dbus_message_unref(reply);
1015 static int list_jobs(DBusConnection *bus, char **args) {
1016 DBusMessage *reply = NULL;
1018 DBusMessageIter iter, sub, sub2;
1021 pager_open_if_enabled();
1023 r = bus_method_call_with_reply (
1025 "org.freedesktop.systemd1",
1026 "/org/freedesktop/systemd1",
1027 "org.freedesktop.systemd1.Manager",
1035 if (!dbus_message_iter_init(reply, &iter) ||
1036 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1037 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1038 log_error("Failed to parse reply.");
1043 dbus_message_iter_recurse(&iter, &sub);
1046 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1048 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1049 const char *name, *type, *state, *job_path, *unit_path;
1053 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1054 log_error("Failed to parse reply.");
1059 dbus_message_iter_recurse(&sub, &sub2);
1061 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1062 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1063 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1064 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1065 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1066 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1067 log_error("Failed to parse reply.");
1072 e = arg_full ? NULL : ellipsize(name, 25, 33);
1073 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1078 dbus_message_iter_next(&sub);
1082 printf("\n%u jobs listed.\n", k);
1088 dbus_message_unref(reply);
1093 static int load_unit(DBusConnection *bus, char **args) {
1099 STRV_FOREACH(name, args+1) {
1100 n = unit_name_mangle(*name);
1101 r = bus_method_call_with_reply (
1103 "org.freedesktop.systemd1",
1104 "/org/freedesktop/systemd1",
1105 "org.freedesktop.systemd1.Manager",
1109 DBUS_TYPE_STRING, n ? &n : name,
1120 static int cancel_job(DBusConnection *bus, char **args) {
1121 DBusMessage *reply = NULL;
1127 if (strv_length(args) <= 1)
1128 return daemon_reload(bus, args);
1130 STRV_FOREACH(name, args+1) {
1134 r = safe_atou(*name, &id);
1136 log_error("Failed to parse job id: %s", strerror(-r));
1139 assert_cc(sizeof(uint32_t) == sizeof(id));
1141 r = bus_method_call_with_reply (
1143 "org.freedesktop.systemd1",
1144 "/org/freedesktop/systemd1",
1145 "org.freedesktop.systemd1.Manager",
1149 DBUS_TYPE_UINT32, &id,
1154 if (!dbus_message_get_args(reply, NULL,
1155 DBUS_TYPE_OBJECT_PATH, &path,
1156 DBUS_TYPE_INVALID)) {
1157 log_error("Failed to parse reply");
1158 dbus_message_unref(reply);
1162 dbus_message_unref(reply);
1164 r = bus_method_call_with_reply (
1166 "org.freedesktop.systemd1",
1168 "org.freedesktop.systemd1.Job",
1181 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1182 DBusMessage *reply = NULL;
1183 dbus_bool_t b = FALSE;
1184 DBusMessageIter iter, sub;
1186 *interface = "org.freedesktop.systemd1.Unit",
1187 *property = "NeedDaemonReload",
1192 /* We ignore all errors here, since this is used to show a warning only */
1194 n = unit_name_mangle(unit);
1195 r = bus_method_call_with_reply (
1197 "org.freedesktop.systemd1",
1198 "/org/freedesktop/systemd1",
1199 "org.freedesktop.systemd1.Manager",
1203 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1209 if (!dbus_message_get_args(reply, NULL,
1210 DBUS_TYPE_OBJECT_PATH, &path,
1214 dbus_message_unref(reply);
1215 r = bus_method_call_with_reply (
1217 "org.freedesktop.systemd1",
1219 "org.freedesktop.DBus.Properties",
1223 DBUS_TYPE_STRING, &interface,
1224 DBUS_TYPE_STRING, &property,
1229 if (!dbus_message_iter_init(reply, &iter) ||
1230 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1233 dbus_message_iter_recurse(&iter, &sub);
1235 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1238 dbus_message_iter_get_basic(&sub, &b);
1242 dbus_message_unref(reply);
1247 typedef struct WaitData {
1252 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1260 dbus_error_init(&error);
1262 log_debug("Got D-Bus request: %s.%s() on %s",
1263 dbus_message_get_interface(message),
1264 dbus_message_get_member(message),
1265 dbus_message_get_path(message));
1267 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1268 log_error("Warning! D-Bus connection terminated.");
1269 dbus_connection_close(connection);
1271 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1273 const char *path, *result, *unit;
1274 dbus_bool_t success = true;
1276 if (dbus_message_get_args(message, &error,
1277 DBUS_TYPE_UINT32, &id,
1278 DBUS_TYPE_OBJECT_PATH, &path,
1279 DBUS_TYPE_STRING, &unit,
1280 DBUS_TYPE_STRING, &result,
1281 DBUS_TYPE_INVALID)) {
1284 p = set_remove(d->set, (char*) path);
1288 d->result = strdup(result);
1293 dbus_error_free(&error);
1294 if (dbus_message_get_args(message, &error,
1295 DBUS_TYPE_UINT32, &id,
1296 DBUS_TYPE_OBJECT_PATH, &path,
1297 DBUS_TYPE_STRING, &result,
1298 DBUS_TYPE_INVALID)) {
1301 /* Compatibility with older systemd versions <
1302 * 183 during upgrades. This should be dropped
1304 p = set_remove(d->set, (char*) path);
1308 d->result = strdup(result);
1313 dbus_error_free(&error);
1314 if (dbus_message_get_args(message, &error,
1315 DBUS_TYPE_UINT32, &id,
1316 DBUS_TYPE_OBJECT_PATH, &path,
1317 DBUS_TYPE_BOOLEAN, &success,
1318 DBUS_TYPE_INVALID)) {
1321 /* Compatibility with older systemd versions <
1322 * 19 during upgrades. This should be dropped
1325 p = set_remove(d->set, (char*) path);
1329 d->result = strdup("failed");
1335 log_error("Failed to parse message: %s", bus_error_message(&error));
1339 dbus_error_free(&error);
1340 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1343 static int enable_wait_for_jobs(DBusConnection *bus) {
1351 dbus_error_init(&error);
1352 dbus_bus_add_match(bus,
1354 "sender='org.freedesktop.systemd1',"
1355 "interface='org.freedesktop.systemd1.Manager',"
1356 "member='JobRemoved',"
1357 "path='/org/freedesktop/systemd1'",
1360 if (dbus_error_is_set(&error)) {
1361 log_error("Failed to add match: %s", bus_error_message(&error));
1362 dbus_error_free(&error);
1366 /* This is slightly dirty, since we don't undo the match registrations. */
1370 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1380 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1381 log_error("Failed to add filter.");
1386 while (!set_isempty(s) &&
1387 dbus_connection_read_write_dispatch(bus, -1))
1390 if (!arg_quiet && d.result) {
1391 if (streq(d.result, "timeout"))
1392 log_error("Job timed out.");
1393 else if (streq(d.result, "canceled"))
1394 log_error("Job canceled.");
1395 else if (streq(d.result, "dependency"))
1396 log_error("A dependency job failed. See system journal for details.");
1397 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1398 log_error("Job failed. See system journal and 'systemctl status' for details.");
1401 if (streq_ptr(d.result, "timeout"))
1403 else if (streq_ptr(d.result, "canceled"))
1405 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1413 /* This is slightly dirty, since we don't undo the filter registration. */
1418 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1419 DBusMessage *reply = NULL;
1420 DBusMessageIter iter, sub;
1422 *interface = "org.freedesktop.systemd1.Unit",
1423 *property = "ActiveState";
1424 const char *path = NULL;
1431 n = unit_name_mangle(name);
1432 r = bus_method_call_with_reply (
1434 "org.freedesktop.systemd1",
1435 "/org/freedesktop/systemd1",
1436 "org.freedesktop.systemd1.Manager",
1440 DBUS_TYPE_STRING, n ? &n : &name,
1444 if ((r != -ENOMEM) && (!quiet))
1449 if (!dbus_message_get_args(reply, NULL,
1450 DBUS_TYPE_OBJECT_PATH, &path,
1451 DBUS_TYPE_INVALID)) {
1452 log_error("Failed to parse reply.");
1457 dbus_message_unref(reply);
1458 r = bus_method_call_with_reply (
1460 "org.freedesktop.systemd1",
1462 "org.freedesktop.DBus.Properties",
1466 DBUS_TYPE_STRING, &interface,
1467 DBUS_TYPE_STRING, &property,
1472 if (!dbus_message_iter_init(reply, &iter) ||
1473 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1474 log_error("Failed to parse reply.");
1479 dbus_message_iter_recurse(&iter, &sub);
1481 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1482 log_error("Failed to parse reply.");
1487 dbus_message_iter_get_basic(&sub, &state);
1492 if (streq(state, "active") || streq(state, "reloading"))
1495 r = 3; /* According to LSB: "program is not running" */
1499 dbus_message_unref(reply);
1504 static void check_triggering_units(
1505 DBusConnection *bus,
1506 const char *unit_name) {
1508 DBusMessage *reply = NULL;
1509 DBusMessageIter iter, sub;
1510 char *service_trigger = NULL;
1511 const char *interface = "org.freedesktop.systemd1.Unit",
1512 *triggered_by_property = "TriggeredBy";
1514 char *unit_path = NULL, *n = NULL;
1515 bool print_warning_label = true;
1518 n = unit_name_mangle(unit_name);
1519 unit_path = unit_dbus_path_from_name(n ? n : unit_name);
1522 log_error("Could not allocate dbus path.");
1526 r = bus_method_call_with_reply (
1528 "org.freedesktop.systemd1",
1530 "org.freedesktop.DBus.Properties",
1534 DBUS_TYPE_STRING, &interface,
1535 DBUS_TYPE_STRING, &triggered_by_property,
1540 if (!dbus_message_iter_init(reply, &iter) ||
1541 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1542 log_error("Failed to parse reply.");
1547 dbus_message_iter_recurse(&iter, &sub);
1548 dbus_message_iter_recurse(&sub, &iter);
1551 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1553 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1554 log_error("Failed to parse reply.");
1558 dbus_message_iter_get_basic(&sub, &service_trigger);
1560 r = check_one_unit(bus, service_trigger, true);
1564 if (print_warning_label) {
1565 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1566 print_warning_label = false;
1568 log_warning(" %s", service_trigger);
1571 dbus_message_iter_next(&sub);
1575 dbus_message_unref(reply);
1580 static int start_unit_one(
1581 DBusConnection *bus,
1588 DBusMessage *reply = NULL;
1597 assert(arg_no_block || s);
1599 n = unit_name_mangle(name);
1600 r = bus_method_call_with_reply (
1602 "org.freedesktop.systemd1",
1603 "/org/freedesktop/systemd1",
1604 "org.freedesktop.systemd1.Manager",
1608 DBUS_TYPE_STRING, n ? (const char **) &n : &name,
1609 DBUS_TYPE_STRING, &mode,
1613 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL ) {
1614 /* There's always a fallback possible for
1615 * legacy actions. */
1621 if (!dbus_message_get_args(reply, error,
1622 DBUS_TYPE_OBJECT_PATH, &path,
1623 DBUS_TYPE_INVALID)) {
1624 log_error("Failed to parse reply: %s", bus_error_message(error));
1629 if (need_daemon_reload(bus, name))
1630 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1631 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1633 if (!arg_no_block) {
1636 if (!(p = strdup(path))) {
1637 log_error("Failed to duplicate path.");
1642 if ((r = set_put(s, p)) < 0) {
1644 log_error("Failed to add path to set.");
1649 /* When stopping a unit warn if it can still be triggered by
1650 * another active unit (socket, path, timer) */
1651 if (!arg_quiet && streq(method, "StopUnit"))
1652 check_triggering_units(bus, name);
1658 dbus_message_unref(reply);
1663 static enum action verb_to_action(const char *verb) {
1664 if (streq(verb, "halt"))
1666 else if (streq(verb, "poweroff"))
1667 return ACTION_POWEROFF;
1668 else if (streq(verb, "reboot"))
1669 return ACTION_REBOOT;
1670 else if (streq(verb, "kexec"))
1671 return ACTION_KEXEC;
1672 else if (streq(verb, "rescue"))
1673 return ACTION_RESCUE;
1674 else if (streq(verb, "emergency"))
1675 return ACTION_EMERGENCY;
1676 else if (streq(verb, "default"))
1677 return ACTION_DEFAULT;
1678 else if (streq(verb, "exit"))
1680 else if (streq(verb, "suspend"))
1681 return ACTION_SUSPEND;
1682 else if (streq(verb, "hibernate"))
1683 return ACTION_HIBERNATE;
1685 return ACTION_INVALID;
1688 static int start_unit(DBusConnection *bus, char **args) {
1690 static const char * const table[_ACTION_MAX] = {
1691 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1692 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1693 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1694 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1695 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1696 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1697 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1698 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1699 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1700 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1701 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1702 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1703 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1704 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1708 const char *method, *mode, *one_name;
1713 dbus_error_init(&error);
1717 ask_password_agent_open_if_enabled();
1719 if (arg_action == ACTION_SYSTEMCTL) {
1721 streq(args[0], "stop") ||
1722 streq(args[0], "condstop") ? "StopUnit" :
1723 streq(args[0], "reload") ? "ReloadUnit" :
1724 streq(args[0], "restart") ? "RestartUnit" :
1726 streq(args[0], "try-restart") ||
1727 streq(args[0], "condrestart") ? "TryRestartUnit" :
1729 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1731 streq(args[0], "reload-or-try-restart") ||
1732 streq(args[0], "condreload") ||
1734 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1738 (streq(args[0], "isolate") ||
1739 streq(args[0], "rescue") ||
1740 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1742 one_name = table[verb_to_action(args[0])];
1745 assert(arg_action < ELEMENTSOF(table));
1746 assert(table[arg_action]);
1748 method = "StartUnit";
1750 mode = (arg_action == ACTION_EMERGENCY ||
1751 arg_action == ACTION_RESCUE ||
1752 arg_action == ACTION_RUNLEVEL2 ||
1753 arg_action == ACTION_RUNLEVEL3 ||
1754 arg_action == ACTION_RUNLEVEL4 ||
1755 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1757 one_name = table[arg_action];
1760 if (!arg_no_block) {
1761 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1762 log_error("Could not watch jobs: %s", strerror(-ret));
1766 if (!(s = set_new(string_hash_func, string_compare_func))) {
1767 log_error("Failed to allocate set.");
1774 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1777 STRV_FOREACH(name, args+1)
1778 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1779 ret = translate_bus_error_to_exit_status(r, &error);
1780 dbus_error_free(&error);
1785 if ((r = wait_for_jobs(bus, s)) < 0) {
1794 dbus_error_free(&error);
1799 /* Ask systemd-logind, which might grant access to unprivileged users
1800 * through PolicyKit */
1801 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1804 dbus_bool_t interactive = true;
1806 polkit_agent_open_if_enabled();
1814 case ACTION_POWEROFF:
1815 method = "PowerOff";
1818 case ACTION_SUSPEND:
1822 case ACTION_HIBERNATE:
1823 method = "Hibernate";
1830 return bus_method_call_with_reply (
1832 "org.freedesktop.login1",
1833 "/org/freedesktop/login1",
1834 "org.freedesktop.login1.Manager",
1838 DBUS_TYPE_BOOLEAN, &interactive,
1845 static int start_special(DBusConnection *bus, char **args) {
1851 a = verb_to_action(args[0]);
1853 if (arg_force >= 2 && geteuid() != 0) {
1854 log_error("Must be root.");
1858 if (arg_force >= 2 &&
1859 (a == ACTION_HALT ||
1860 a == ACTION_POWEROFF ||
1861 a == ACTION_REBOOT))
1864 if (arg_force >= 1 &&
1865 (a == ACTION_HALT ||
1866 a == ACTION_POWEROFF ||
1867 a == ACTION_REBOOT ||
1868 a == ACTION_KEXEC ||
1870 return daemon_reload(bus, args);
1872 /* first try logind, to allow authentication with polkit */
1873 if (geteuid() != 0 &&
1874 (a == ACTION_POWEROFF ||
1875 a == ACTION_REBOOT ||
1876 a == ACTION_SUSPEND ||
1877 a == ACTION_HIBERNATE)) {
1878 r = reboot_with_logind(bus, a);
1883 r = start_unit(bus, args);
1890 static int check_unit(DBusConnection *bus, char **args) {
1892 int r = 3; /* According to LSB: "program is not running" */
1897 STRV_FOREACH(name, args+1) {
1898 int state = check_one_unit(bus, *name, arg_quiet);
1908 static int kill_unit(DBusConnection *bus, char **args) {
1915 arg_kill_who = "all";
1917 STRV_FOREACH(name, args+1) {
1918 n = unit_name_mangle(*name);
1919 r = bus_method_call_with_reply (
1921 "org.freedesktop.systemd1",
1922 "/org/freedesktop/systemd1",
1923 "org.freedesktop.systemd1.Manager",
1927 DBUS_TYPE_STRING, n ? &n : name,
1928 DBUS_TYPE_STRING, &arg_kill_who,
1929 DBUS_TYPE_INT32, &arg_signal,
1938 typedef struct ExecStatusInfo {
1946 usec_t start_timestamp;
1947 usec_t exit_timestamp;
1952 LIST_FIELDS(struct ExecStatusInfo, exec);
1955 static void exec_status_info_free(ExecStatusInfo *i) {
1964 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1965 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1966 DBusMessageIter sub2, sub3;
1970 int32_t code, status;
1976 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1979 dbus_message_iter_recurse(sub, &sub2);
1981 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1984 if (!(i->path = strdup(path)))
1987 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1988 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1992 dbus_message_iter_recurse(&sub2, &sub3);
1993 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1994 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1995 dbus_message_iter_next(&sub3);
2000 if (!(i->argv = new0(char*, n+1)))
2004 dbus_message_iter_recurse(&sub2, &sub3);
2005 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2008 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2009 dbus_message_iter_get_basic(&sub3, &s);
2010 dbus_message_iter_next(&sub3);
2012 if (!(i->argv[n++] = strdup(s)))
2016 if (!dbus_message_iter_next(&sub2) ||
2017 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2018 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2019 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2020 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2021 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2022 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2023 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2024 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2028 i->start_timestamp = (usec_t) start_timestamp;
2029 i->exit_timestamp = (usec_t) exit_timestamp;
2030 i->pid = (pid_t) pid;
2037 typedef struct UnitStatusInfo {
2039 const char *load_state;
2040 const char *active_state;
2041 const char *sub_state;
2042 const char *unit_file_state;
2044 const char *description;
2045 const char *following;
2047 char **documentation;
2049 const char *fragment_path;
2050 const char *source_path;
2051 const char *default_control_group;
2053 const char *load_error;
2056 usec_t inactive_exit_timestamp;
2057 usec_t inactive_exit_timestamp_monotonic;
2058 usec_t active_enter_timestamp;
2059 usec_t active_exit_timestamp;
2060 usec_t inactive_enter_timestamp;
2062 bool need_daemon_reload;
2067 const char *status_text;
2070 usec_t start_timestamp;
2071 usec_t exit_timestamp;
2073 int exit_code, exit_status;
2075 usec_t condition_timestamp;
2076 bool condition_result;
2079 unsigned n_accepted;
2080 unsigned n_connections;
2084 const char *sysfs_path;
2086 /* Mount, Automount */
2092 LIST_HEAD(ExecStatusInfo, exec);
2095 static void print_status_info(UnitStatusInfo *i) {
2097 const char *on, *off, *ss;
2099 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2100 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2105 /* This shows pretty information about a unit. See
2106 * print_property() for a low-level property printer */
2108 printf("%s", strna(i->id));
2110 if (i->description && !streq_ptr(i->id, i->description))
2111 printf(" - %s", i->description);
2116 printf("\t Follow: unit currently follows state of %s\n", i->following);
2118 if (streq_ptr(i->load_state, "error")) {
2119 on = ansi_highlight_red(true);
2120 off = ansi_highlight_red(false);
2124 path = i->source_path ? i->source_path : i->fragment_path;
2127 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2128 else if (path && i->unit_file_state)
2129 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2131 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2133 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2135 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2137 if (streq_ptr(i->active_state, "failed")) {
2138 on = ansi_highlight_red(true);
2139 off = ansi_highlight_red(false);
2140 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2141 on = ansi_highlight_green(true);
2142 off = ansi_highlight_green(false);
2147 printf("\t Active: %s%s (%s)%s",
2149 strna(i->active_state),
2153 printf("\t Active: %s%s%s",
2155 strna(i->active_state),
2158 if (!isempty(i->result) && !streq(i->result, "success"))
2159 printf(" (Result: %s)", i->result);
2161 timestamp = (streq_ptr(i->active_state, "active") ||
2162 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2163 (streq_ptr(i->active_state, "inactive") ||
2164 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2165 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2166 i->active_exit_timestamp;
2168 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2169 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2172 printf(" since %s; %s\n", s2, s1);
2174 printf(" since %s\n", s2);
2178 if (!i->condition_result && i->condition_timestamp > 0) {
2179 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2180 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2183 printf("\t start condition failed at %s; %s\n", s2, s1);
2185 printf("\t start condition failed at %s\n", s2);
2189 printf("\t Device: %s\n", i->sysfs_path);
2191 printf("\t Where: %s\n", i->where);
2193 printf("\t What: %s\n", i->what);
2195 if (!strv_isempty(i->documentation)) {
2199 STRV_FOREACH(t, i->documentation) {
2201 printf("\t Docs: %s\n", *t);
2204 printf("\t %s\n", *t);
2209 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2211 LIST_FOREACH(exec, p, i->exec) {
2215 /* Only show exited processes here */
2219 t = strv_join(p->argv, " ");
2220 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2223 good = is_clean_exit_lsb(p->code, p->status);
2225 on = ansi_highlight_red(true);
2226 off = ansi_highlight_red(false);
2230 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2232 if (p->code == CLD_EXITED) {
2235 printf("status=%i", p->status);
2237 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2242 printf("signal=%s", signal_to_string(p->status));
2244 printf(")%s\n", off);
2246 if (i->main_pid == p->pid &&
2247 i->start_timestamp == p->start_timestamp &&
2248 i->exit_timestamp == p->start_timestamp)
2249 /* Let's not show this twice */
2252 if (p->pid == i->control_pid)
2256 if (i->main_pid > 0 || i->control_pid > 0) {
2259 if (i->main_pid > 0) {
2260 printf("Main PID: %u", (unsigned) i->main_pid);
2264 get_process_comm(i->main_pid, &t);
2269 } else if (i->exit_code > 0) {
2270 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2272 if (i->exit_code == CLD_EXITED) {
2275 printf("status=%i", i->exit_status);
2277 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2282 printf("signal=%s", signal_to_string(i->exit_status));
2287 if (i->main_pid > 0 && i->control_pid > 0)
2290 if (i->control_pid > 0) {
2293 printf(" Control: %u", (unsigned) i->control_pid);
2295 get_process_comm(i->control_pid, &t);
2306 printf("\t Status: \"%s\"\n", i->status_text);
2308 if (i->default_control_group) {
2311 printf("\t CGroup: %s\n", i->default_control_group);
2313 if (arg_transport != TRANSPORT_SSH) {
2323 if (i->main_pid > 0)
2324 extra[k++] = i->main_pid;
2326 if (i->control_pid > 0)
2327 extra[k++] = i->control_pid;
2329 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2333 if (i->id && arg_transport != TRANSPORT_SSH) {
2335 arg_lines * OUTPUT_SHOW_ALL |
2336 arg_follow * OUTPUT_FOLLOW |
2337 !arg_quiet * OUTPUT_WARN_CUTOFF |
2338 on_tty() * OUTPUT_COLOR;
2341 show_journal_by_unit(i->id, arg_output, 0,
2342 i->inactive_exit_timestamp_monotonic,
2346 if (i->need_daemon_reload)
2347 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2348 ansi_highlight_red(true),
2349 ansi_highlight_red(false),
2350 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2353 static void show_unit_help(UnitStatusInfo *i) {
2358 if (!i->documentation) {
2359 log_info("Documentation for %s not known.", i->id);
2363 STRV_FOREACH(p, i->documentation) {
2365 if (startswith(*p, "man:")) {
2368 char *page = NULL, *section = NULL;
2369 const char *args[4] = { "man", NULL, NULL, NULL };
2374 if ((*p)[k-1] == ')')
2375 e = strrchr(*p, '(');
2378 page = strndup((*p) + 4, e - *p - 4);
2384 section = strndup(e + 1, *p + k - e - 2);
2398 log_error("Failed to fork: %m");
2406 execvp(args[0], (char**) args);
2407 log_error("Failed to execute man: %m");
2408 _exit(EXIT_FAILURE);
2414 wait_for_terminate(pid, NULL);
2416 log_info("Can't show: %s", *p);
2420 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2426 switch (dbus_message_iter_get_arg_type(iter)) {
2428 case DBUS_TYPE_STRING: {
2431 dbus_message_iter_get_basic(iter, &s);
2434 if (streq(name, "Id"))
2436 else if (streq(name, "LoadState"))
2438 else if (streq(name, "ActiveState"))
2439 i->active_state = s;
2440 else if (streq(name, "SubState"))
2442 else if (streq(name, "Description"))
2444 else if (streq(name, "FragmentPath"))
2445 i->fragment_path = s;
2446 else if (streq(name, "SourcePath"))
2448 else if (streq(name, "DefaultControlGroup"))
2449 i->default_control_group = s;
2450 else if (streq(name, "StatusText"))
2452 else if (streq(name, "SysFSPath"))
2454 else if (streq(name, "Where"))
2456 else if (streq(name, "What"))
2458 else if (streq(name, "Following"))
2460 else if (streq(name, "UnitFileState"))
2461 i->unit_file_state = s;
2462 else if (streq(name, "Result"))
2469 case DBUS_TYPE_BOOLEAN: {
2472 dbus_message_iter_get_basic(iter, &b);
2474 if (streq(name, "Accept"))
2476 else if (streq(name, "NeedDaemonReload"))
2477 i->need_daemon_reload = b;
2478 else if (streq(name, "ConditionResult"))
2479 i->condition_result = b;
2484 case DBUS_TYPE_UINT32: {
2487 dbus_message_iter_get_basic(iter, &u);
2489 if (streq(name, "MainPID")) {
2491 i->main_pid = (pid_t) u;
2494 } else if (streq(name, "ControlPID"))
2495 i->control_pid = (pid_t) u;
2496 else if (streq(name, "ExecMainPID")) {
2498 i->main_pid = (pid_t) u;
2499 } else if (streq(name, "NAccepted"))
2501 else if (streq(name, "NConnections"))
2502 i->n_connections = u;
2507 case DBUS_TYPE_INT32: {
2510 dbus_message_iter_get_basic(iter, &j);
2512 if (streq(name, "ExecMainCode"))
2513 i->exit_code = (int) j;
2514 else if (streq(name, "ExecMainStatus"))
2515 i->exit_status = (int) j;
2520 case DBUS_TYPE_UINT64: {
2523 dbus_message_iter_get_basic(iter, &u);
2525 if (streq(name, "ExecMainStartTimestamp"))
2526 i->start_timestamp = (usec_t) u;
2527 else if (streq(name, "ExecMainExitTimestamp"))
2528 i->exit_timestamp = (usec_t) u;
2529 else if (streq(name, "ActiveEnterTimestamp"))
2530 i->active_enter_timestamp = (usec_t) u;
2531 else if (streq(name, "InactiveEnterTimestamp"))
2532 i->inactive_enter_timestamp = (usec_t) u;
2533 else if (streq(name, "InactiveExitTimestamp"))
2534 i->inactive_exit_timestamp = (usec_t) u;
2535 else if (streq(name, "InactiveExitTimestampMonotonic"))
2536 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2537 else if (streq(name, "ActiveExitTimestamp"))
2538 i->active_exit_timestamp = (usec_t) u;
2539 else if (streq(name, "ConditionTimestamp"))
2540 i->condition_timestamp = (usec_t) u;
2545 case DBUS_TYPE_ARRAY: {
2547 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2548 startswith(name, "Exec")) {
2549 DBusMessageIter sub;
2551 dbus_message_iter_recurse(iter, &sub);
2552 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2553 ExecStatusInfo *info;
2556 if (!(info = new0(ExecStatusInfo, 1)))
2559 if (!(info->name = strdup(name))) {
2564 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2569 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2571 dbus_message_iter_next(&sub);
2573 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2574 streq(name, "Documentation")) {
2576 DBusMessageIter sub;
2578 dbus_message_iter_recurse(iter, &sub);
2579 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2583 dbus_message_iter_get_basic(&sub, &s);
2585 l = strv_append(i->documentation, s);
2589 strv_free(i->documentation);
2590 i->documentation = l;
2592 dbus_message_iter_next(&sub);
2599 case DBUS_TYPE_STRUCT: {
2601 if (streq(name, "LoadError")) {
2602 DBusMessageIter sub;
2603 const char *n, *message;
2606 dbus_message_iter_recurse(iter, &sub);
2608 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2612 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2616 if (!isempty(message))
2617 i->load_error = message;
2627 static int print_property(const char *name, DBusMessageIter *iter) {
2631 /* This is a low-level property printer, see
2632 * print_status_info() for the nicer output */
2634 if (arg_property && !strv_find(arg_property, name))
2637 switch (dbus_message_iter_get_arg_type(iter)) {
2639 case DBUS_TYPE_STRUCT: {
2640 DBusMessageIter sub;
2641 dbus_message_iter_recurse(iter, &sub);
2643 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2646 dbus_message_iter_get_basic(&sub, &u);
2649 printf("%s=%u\n", name, (unsigned) u);
2651 printf("%s=\n", name);
2654 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2657 dbus_message_iter_get_basic(&sub, &s);
2659 if (arg_all || s[0])
2660 printf("%s=%s\n", name, s);
2663 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2664 const char *a = NULL, *b = NULL;
2666 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2667 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2669 if (arg_all || !isempty(a) || !isempty(b))
2670 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2678 case DBUS_TYPE_ARRAY:
2680 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2681 DBusMessageIter sub, sub2;
2683 dbus_message_iter_recurse(iter, &sub);
2684 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2688 dbus_message_iter_recurse(&sub, &sub2);
2690 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2691 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2692 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2694 dbus_message_iter_next(&sub);
2699 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2700 DBusMessageIter sub, sub2;
2702 dbus_message_iter_recurse(iter, &sub);
2703 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2704 const char *type, *path;
2706 dbus_message_iter_recurse(&sub, &sub2);
2708 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2709 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2710 printf("%s=%s\n", type, path);
2712 dbus_message_iter_next(&sub);
2717 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2718 DBusMessageIter sub, sub2;
2720 dbus_message_iter_recurse(iter, &sub);
2721 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2723 uint64_t value, next_elapse;
2725 dbus_message_iter_recurse(&sub, &sub2);
2727 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2728 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2729 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2730 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2732 printf("%s={ value=%s ; next_elapse=%s }\n",
2734 format_timespan(timespan1, sizeof(timespan1), value),
2735 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2738 dbus_message_iter_next(&sub);
2743 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2744 DBusMessageIter sub, sub2;
2746 dbus_message_iter_recurse(iter, &sub);
2747 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2748 const char *controller, *attr, *value;
2750 dbus_message_iter_recurse(&sub, &sub2);
2752 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2753 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2754 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2756 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2762 dbus_message_iter_next(&sub);
2767 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2768 DBusMessageIter sub;
2770 dbus_message_iter_recurse(iter, &sub);
2771 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2772 ExecStatusInfo info;
2775 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2776 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2779 t = strv_join(info.argv, " ");
2781 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2785 yes_no(info.ignore),
2786 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2787 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2788 (unsigned) info. pid,
2789 sigchld_code_to_string(info.code),
2791 info.code == CLD_EXITED ? "" : "/",
2792 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2798 strv_free(info.argv);
2800 dbus_message_iter_next(&sub);
2809 if (generic_print_property(name, iter, arg_all) > 0)
2813 printf("%s=[unprintable]\n", name);
2818 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2819 DBusMessage *reply = NULL;
2820 const char *interface = "";
2822 DBusMessageIter iter, sub, sub2, sub3;
2823 UnitStatusInfo info;
2831 r = bus_method_call_with_reply (
2833 "org.freedesktop.systemd1",
2835 "org.freedesktop.DBus.Properties",
2839 DBUS_TYPE_STRING, &interface,
2844 if (!dbus_message_iter_init(reply, &iter) ||
2845 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2846 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2847 log_error("Failed to parse reply.");
2852 dbus_message_iter_recurse(&iter, &sub);
2859 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2862 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2863 log_error("Failed to parse reply.");
2868 dbus_message_iter_recurse(&sub, &sub2);
2870 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2871 log_error("Failed to parse reply.");
2876 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2877 log_error("Failed to parse reply.");
2882 dbus_message_iter_recurse(&sub2, &sub3);
2884 if (show_properties)
2885 r = print_property(name, &sub3);
2887 r = status_property(name, &sub3, &info);
2890 log_error("Failed to parse reply.");
2895 dbus_message_iter_next(&sub);
2900 if (!show_properties) {
2901 if (streq(verb, "help"))
2902 show_unit_help(&info);
2904 print_status_info(&info);
2907 strv_free(info.documentation);
2909 if (!streq_ptr(info.active_state, "active") &&
2910 !streq_ptr(info.active_state, "reloading") &&
2911 streq(verb, "status"))
2912 /* According to LSB: "program not running" */
2915 while ((p = info.exec)) {
2916 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2917 exec_status_info_free(p);
2922 dbus_message_unref(reply);
2927 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2928 DBusMessage *reply = NULL;
2929 const char *path = NULL;
2933 dbus_error_init(&error);
2935 r = bus_method_call_with_reply (
2937 "org.freedesktop.systemd1",
2938 "/org/freedesktop/systemd1",
2939 "org.freedesktop.systemd1.Manager",
2943 DBUS_TYPE_UINT32, &pid,
2948 if (!dbus_message_get_args(reply, &error,
2949 DBUS_TYPE_OBJECT_PATH, &path,
2950 DBUS_TYPE_INVALID)) {
2951 log_error("Failed to parse reply: %s", bus_error_message(&error));
2956 r = show_one(verb, bus, path, false, new_line);
2960 dbus_message_unref(reply);
2962 dbus_error_free(&error);
2967 static int show(DBusConnection *bus, char **args) {
2969 bool show_properties, new_line = false;
2975 show_properties = streq(args[0], "show");
2977 if (show_properties)
2978 pager_open_if_enabled();
2980 if (show_properties && strv_length(args) <= 1) {
2981 /* If not argument is specified inspect the manager
2984 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2987 STRV_FOREACH(name, args+1) {
2990 if (safe_atou32(*name, &id) < 0) {
2992 /* Interpret as unit name */
2994 n = unit_name_mangle(*name);
2995 p = unit_dbus_path_from_name(n ? n : *name);
3000 r = show_one(args[0], bus, p, show_properties, &new_line);
3006 } else if (show_properties) {
3008 /* Interpret as job id */
3011 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3014 r = show_one(args[0], bus, p, show_properties, &new_line);
3022 /* Interpret as PID */
3024 r = show_one_by_pid(args[0], bus, id, &new_line);
3033 static int dump(DBusConnection *bus, char **args) {
3034 DBusMessage *reply = NULL;
3039 dbus_error_init(&error);
3041 pager_open_if_enabled();
3043 r = bus_method_call_with_reply (
3045 "org.freedesktop.systemd1",
3046 "/org/freedesktop/systemd1",
3047 "org.freedesktop.systemd1.Manager",
3055 if (!dbus_message_get_args(reply, &error,
3056 DBUS_TYPE_STRING, &text,
3057 DBUS_TYPE_INVALID)) {
3058 log_error("Failed to parse reply: %s", bus_error_message(&error));
3063 fputs(text, stdout);
3067 dbus_message_unref(reply);
3069 dbus_error_free(&error);
3074 static int snapshot(DBusConnection *bus, char **args) {
3075 DBusMessage *reply = NULL;
3078 dbus_bool_t cleanup = FALSE;
3079 DBusMessageIter iter, sub;
3081 *name = "", *path, *id,
3082 *interface = "org.freedesktop.systemd1.Unit",
3086 dbus_error_init(&error);
3088 if (strv_length(args) > 1)
3091 n = unit_name_mangle(name);
3092 r = bus_method_call_with_reply (
3094 "org.freedesktop.systemd1",
3095 "/org/freedesktop/systemd1",
3096 "org.freedesktop.systemd1.Manager",
3100 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3101 DBUS_TYPE_BOOLEAN, &cleanup,
3107 if (!dbus_message_get_args(reply, &error,
3108 DBUS_TYPE_OBJECT_PATH, &path,
3109 DBUS_TYPE_INVALID)) {
3110 log_error("Failed to parse reply: %s", bus_error_message(&error));
3115 dbus_message_unref(reply);
3116 r = bus_method_call_with_reply (
3118 "org.freedesktop.systemd1",
3120 "org.freedesktop.DBus.Properties",
3124 DBUS_TYPE_STRING, &interface,
3125 DBUS_TYPE_STRING, &property,
3130 if (!dbus_message_iter_init(reply, &iter) ||
3131 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3132 log_error("Failed to parse reply.");
3137 dbus_message_iter_recurse(&iter, &sub);
3139 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3140 log_error("Failed to parse reply.");
3145 dbus_message_iter_get_basic(&sub, &id);
3152 dbus_message_unref(reply);
3154 dbus_error_free(&error);
3159 static int delete_snapshot(DBusConnection *bus, char **args) {
3160 DBusMessage *reply = NULL;
3167 dbus_error_init(&error);
3169 STRV_FOREACH(name, args+1) {
3170 const char *path = NULL;
3173 n = unit_name_mangle(*name);
3174 r = bus_method_call_with_reply (
3176 "org.freedesktop.systemd1",
3177 "/org/freedesktop/systemd1",
3178 "org.freedesktop.systemd1.Manager",
3182 DBUS_TYPE_STRING, n ? &n : name,
3188 if (!dbus_message_get_args(reply, &error,
3189 DBUS_TYPE_OBJECT_PATH, &path,
3190 DBUS_TYPE_INVALID)) {
3191 log_error("Failed to parse reply: %s", bus_error_message(&error));
3193 dbus_message_unref(reply);
3194 dbus_error_free(&error);
3197 dbus_message_unref(reply);
3199 r = bus_method_call_with_reply (
3201 "org.freedesktop.systemd1",
3203 "org.freedesktop.systemd1.Snapshot",
3216 static int daemon_reload(DBusConnection *bus, char **args) {
3220 if (arg_action == ACTION_RELOAD)
3222 else if (arg_action == ACTION_REEXEC)
3223 method = "Reexecute";
3225 assert(arg_action == ACTION_SYSTEMCTL);
3228 streq(args[0], "clear-jobs") ||
3229 streq(args[0], "cancel") ? "ClearJobs" :
3230 streq(args[0], "daemon-reexec") ? "Reexecute" :
3231 streq(args[0], "reset-failed") ? "ResetFailed" :
3232 streq(args[0], "halt") ? "Halt" :
3233 streq(args[0], "poweroff") ? "PowerOff" :
3234 streq(args[0], "reboot") ? "Reboot" :
3235 streq(args[0], "kexec") ? "KExec" :
3236 streq(args[0], "exit") ? "Exit" :
3237 /* "daemon-reload" */ "Reload";
3240 r = bus_method_call_with_reply (
3242 "org.freedesktop.systemd1",
3243 "/org/freedesktop/systemd1",
3244 "org.freedesktop.systemd1.Manager",
3250 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3251 /* There's always a fallback possible for
3252 * legacy actions. */
3254 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3255 /* On reexecution, we expect a disconnect, not
3262 static int reset_failed(DBusConnection *bus, char **args) {
3266 if (strv_length(args) <= 1)
3267 return daemon_reload(bus, args);
3269 STRV_FOREACH(name, args+1) {
3270 n = unit_name_mangle(*name);
3271 r = bus_method_call_with_reply (
3273 "org.freedesktop.systemd1",
3274 "/org/freedesktop/systemd1",
3275 "org.freedesktop.systemd1.Manager",
3279 DBUS_TYPE_STRING, n ? &n : name,
3290 static int show_enviroment(DBusConnection *bus, char **args) {
3291 DBusMessage *reply = NULL;
3292 DBusMessageIter iter, sub, sub2;
3295 *interface = "org.freedesktop.systemd1.Manager",
3296 *property = "Environment";
3298 pager_open_if_enabled();
3300 r = bus_method_call_with_reply (
3302 "org.freedesktop.systemd1",
3303 "/org/freedesktop/systemd1",
3304 "org.freedesktop.DBus.Properties",
3308 DBUS_TYPE_STRING, &interface,
3309 DBUS_TYPE_STRING, &property,
3314 if (!dbus_message_iter_init(reply, &iter) ||
3315 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3316 log_error("Failed to parse reply.");
3321 dbus_message_iter_recurse(&iter, &sub);
3323 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3324 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3325 log_error("Failed to parse reply.");
3330 dbus_message_iter_recurse(&sub, &sub2);
3332 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3335 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3336 log_error("Failed to parse reply.");
3341 dbus_message_iter_get_basic(&sub2, &text);
3342 printf("%s\n", text);
3344 dbus_message_iter_next(&sub2);
3351 dbus_message_unref(reply);
3356 static int switch_root(DBusConnection *bus, char **args) {
3358 const char *root, *init;
3360 l = strv_length(args);
3361 if (l < 2 || l > 3) {
3362 log_error("Wrong number of arguments.");
3367 init = l >= 3 ? args[2] : "";
3369 return bus_method_call_with_reply (
3371 "org.freedesktop.systemd1",
3372 "/org/freedesktop/systemd1",
3373 "org.freedesktop.systemd1.Manager",
3377 DBUS_TYPE_STRING, &root,
3378 DBUS_TYPE_STRING, &init,
3382 static int set_environment(DBusConnection *bus, char **args) {
3383 DBusMessage *m = NULL, *reply = NULL;
3387 DBusMessageIter iter, sub;
3390 dbus_error_init(&error);
3392 method = streq(args[0], "set-environment")
3394 : "UnsetEnvironment";
3396 if (!(m = dbus_message_new_method_call(
3397 "org.freedesktop.systemd1",
3398 "/org/freedesktop/systemd1",
3399 "org.freedesktop.systemd1.Manager",
3402 log_error("Could not allocate message.");
3406 dbus_message_iter_init_append(m, &iter);
3408 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3409 log_error("Could not append arguments to message.");
3414 STRV_FOREACH(name, args+1)
3415 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3416 log_error("Could not append arguments to message.");
3421 if (!dbus_message_iter_close_container(&iter, &sub)) {
3422 log_error("Could not append arguments to message.");
3427 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3428 log_error("Failed to issue method call: %s", bus_error_message(&error));
3437 dbus_message_unref(m);
3440 dbus_message_unref(reply);
3442 dbus_error_free(&error);
3447 static int enable_sysv_units(char **args) {
3450 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3451 const char *verb = args[0];
3452 unsigned f = 1, t = 1;
3455 if (arg_scope != UNIT_FILE_SYSTEM)
3458 if (!streq(verb, "enable") &&
3459 !streq(verb, "disable") &&
3460 !streq(verb, "is-enabled"))
3463 /* Processes all SysV units, and reshuffles the array so that
3464 * afterwards only the native units remain */
3467 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, NULL, NULL, NULL);
3472 for (f = 1; args[f]; f++) {
3475 bool found_native = false, found_sysv;
3477 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3478 char **k, *l, *q = NULL;
3485 if (!endswith(name, ".service"))
3488 if (path_is_absolute(name))
3491 STRV_FOREACH(k, paths.unit_path) {
3494 if (!isempty(arg_root))
3495 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3497 asprintf(&p, "%s/%s", *k, name);
3504 found_native = access(p, F_OK) >= 0;
3515 if (!isempty(arg_root))
3516 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3518 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3524 p[strlen(p) - sizeof(".service") + 1] = 0;
3525 found_sysv = access(p, F_OK) >= 0;
3532 /* Mark this entry, so that we don't try enabling it as native unit */
3533 args[f] = (char*) "";
3535 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3537 if (!isempty(arg_root))
3538 argv[c++] = q = strappend("--root=", arg_root);
3540 argv[c++] = path_get_file_name(p);
3542 streq(verb, "enable") ? "on" :
3543 streq(verb, "disable") ? "off" : "--level=5";
3546 l = strv_join((char**)argv, " ");
3554 log_info("Executing %s", l);
3559 log_error("Failed to fork: %m");
3564 } else if (pid == 0) {
3567 execv(argv[0], (char**) argv);
3568 _exit(EXIT_FAILURE);
3574 j = wait_for_terminate(pid, &status);
3576 log_error("Failed to wait for child: %s", strerror(-r));
3581 if (status.si_code == CLD_EXITED) {
3582 if (streq(verb, "is-enabled")) {
3583 if (status.si_status == 0) {
3592 } else if (status.si_status != 0) {
3603 lookup_paths_free(&paths);
3605 /* Drop all SysV units */
3606 for (f = 1, t = 1; args[f]; f++) {
3608 if (isempty(args[f]))
3611 args[t++] = args[f];
3620 static int enable_unit(DBusConnection *bus, char **args) {
3621 const char *verb = args[0];
3622 UnitFileChange *changes = NULL;
3623 unsigned n_changes = 0, i;
3624 int carries_install_info = -1;
3625 DBusMessage *m = NULL, *reply = NULL;
3629 r = enable_sysv_units(args);
3636 dbus_error_init(&error);
3638 if (!bus || avoid_bus()) {
3639 if (streq(verb, "enable")) {
3640 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3641 carries_install_info = r;
3642 } else if (streq(verb, "disable"))
3643 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3644 else if (streq(verb, "reenable")) {
3645 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3646 carries_install_info = r;
3647 } else if (streq(verb, "link"))
3648 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3649 else if (streq(verb, "preset")) {
3650 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3651 carries_install_info = r;
3652 } else if (streq(verb, "mask"))
3653 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3654 else if (streq(verb, "unmask"))
3655 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3657 assert_not_reached("Unknown verb");
3660 log_error("Operation failed: %s", strerror(-r));
3665 for (i = 0; i < n_changes; i++) {
3666 if (changes[i].type == UNIT_FILE_SYMLINK)
3667 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3669 log_info("rm '%s'", changes[i].path);
3675 bool send_force = true, expect_carries_install_info = false;
3677 DBusMessageIter iter, sub, sub2;
3679 if (streq(verb, "enable")) {
3680 method = "EnableUnitFiles";
3681 expect_carries_install_info = true;
3682 } else if (streq(verb, "disable")) {
3683 method = "DisableUnitFiles";
3685 } else if (streq(verb, "reenable")) {
3686 method = "ReenableUnitFiles";
3687 expect_carries_install_info = true;
3688 } else if (streq(verb, "link"))
3689 method = "LinkUnitFiles";
3690 else if (streq(verb, "preset")) {
3691 method = "PresetUnitFiles";
3692 expect_carries_install_info = true;
3693 } else if (streq(verb, "mask"))
3694 method = "MaskUnitFiles";
3695 else if (streq(verb, "unmask")) {
3696 method = "UnmaskUnitFiles";
3699 assert_not_reached("Unknown verb");
3701 m = dbus_message_new_method_call(
3702 "org.freedesktop.systemd1",
3703 "/org/freedesktop/systemd1",
3704 "org.freedesktop.systemd1.Manager",
3711 dbus_message_iter_init_append(m, &iter);
3713 r = bus_append_strv_iter(&iter, args+1);
3715 log_error("Failed to append unit files.");
3720 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3721 log_error("Failed to append runtime boolean.");
3729 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3730 log_error("Failed to append force boolean.");
3736 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3738 log_error("Failed to issue method call: %s", bus_error_message(&error));
3743 if (!dbus_message_iter_init(reply, &iter)) {
3744 log_error("Failed to initialize iterator.");
3748 if (expect_carries_install_info) {
3749 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3751 log_error("Failed to parse reply.");
3755 carries_install_info = b;
3758 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3759 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3760 log_error("Failed to parse reply.");
3765 dbus_message_iter_recurse(&iter, &sub);
3766 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3767 const char *type, *path, *source;
3769 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3770 log_error("Failed to parse reply.");
3775 dbus_message_iter_recurse(&sub, &sub2);
3777 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3778 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3779 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3780 log_error("Failed to parse reply.");
3786 if (streq(type, "symlink"))
3787 log_info("ln -s '%s' '%s'", source, path);
3789 log_info("rm '%s'", path);
3792 dbus_message_iter_next(&sub);
3795 /* Try to reload if enabeld */
3797 r = daemon_reload(bus, args);
3800 if (carries_install_info == 0)
3801 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3805 dbus_message_unref(m);
3808 dbus_message_unref(reply);
3810 unit_file_changes_free(changes, n_changes);
3812 dbus_error_free(&error);
3816 static int unit_is_enabled(DBusConnection *bus, char **args) {
3819 DBusMessage *reply = NULL;
3823 dbus_error_init(&error);
3825 r = enable_sysv_units(args);
3831 if (!bus || avoid_bus()) {
3833 STRV_FOREACH(name, args+1) {
3834 UnitFileState state;
3836 state = unit_file_get_state(arg_scope, arg_root, *name);
3842 if (state == UNIT_FILE_ENABLED ||
3843 state == UNIT_FILE_ENABLED_RUNTIME ||
3844 state == UNIT_FILE_STATIC)
3848 puts(unit_file_state_to_string(state));
3852 STRV_FOREACH(name, args+1) {
3855 r = bus_method_call_with_reply (
3857 "org.freedesktop.systemd1",
3858 "/org/freedesktop/systemd1",
3859 "org.freedesktop.systemd1.Manager",
3863 DBUS_TYPE_STRING, name,
3868 if (!dbus_message_get_args(reply, &error,
3869 DBUS_TYPE_STRING, &s,
3870 DBUS_TYPE_INVALID)) {
3871 log_error("Failed to parse reply: %s", bus_error_message(&error));
3876 dbus_message_unref(reply);
3879 if (streq(s, "enabled") ||
3880 streq(s, "enabled-runtime") ||
3889 r = enabled ? 0 : 1;
3893 dbus_message_unref(reply);
3895 dbus_error_free(&error);
3899 static int systemctl_help(void) {
3901 pager_open_if_enabled();
3903 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3904 "Query or send control commands to the systemd manager.\n\n"
3905 " -h --help Show this help\n"
3906 " --version Show package version\n"
3907 " -t --type=TYPE List only units of a particular type\n"
3908 " -p --property=NAME Show only properties by this name\n"
3909 " -a --all Show all units/properties, including dead/empty ones\n"
3910 " --failed Show only failed units\n"
3911 " --full Don't ellipsize unit names on output\n"
3912 " --fail When queueing a new job, fail if conflicting jobs are\n"
3914 " --ignore-dependencies\n"
3915 " When queueing a new job, ignore all its dependencies\n"
3916 " --kill-who=WHO Who to send signal to\n"
3917 " -s --signal=SIGNAL Which signal to send\n"
3918 " -H --host=[USER@]HOST\n"
3919 " Show information for remote host\n"
3920 " -P --privileged Acquire privileges before execution\n"
3921 " -q --quiet Suppress output\n"
3922 " --no-block Do not wait until operation finished\n"
3923 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3924 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3926 " --no-legend Do not print a legend (column headers and hints)\n"
3927 " --no-pager Do not pipe output into a pager\n"
3928 " --no-ask-password\n"
3929 " Do not ask for system passwords\n"
3930 " --order When generating graph for dot, show only order\n"
3931 " --require When generating graph for dot, show only requirement\n"
3932 " --system Connect to system manager\n"
3933 " --user Connect to user service manager\n"
3934 " --global Enable/disable unit files globally\n"
3935 " -f --force When enabling unit files, override existing symlinks\n"
3936 " When shutting down, execute action immediately\n"
3937 " --root=PATH Enable unit files in the specified root directory\n"
3938 " --runtime Enable unit files only temporarily until next reboot\n"
3939 " -n --lines=INTEGER Journal entries to show\n"
3940 " --follow Follow journal\n"
3941 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3942 " verbose, export, json, cat)\n\n"
3944 " list-units List loaded units\n"
3945 " start [NAME...] Start (activate) one or more units\n"
3946 " stop [NAME...] Stop (deactivate) one or more units\n"
3947 " reload [NAME...] Reload one or more units\n"
3948 " restart [NAME...] Start or restart one or more units\n"
3949 " try-restart [NAME...] Restart one or more units if active\n"
3950 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3951 " otherwise start or restart\n"
3952 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3953 " otherwise restart if active\n"
3954 " isolate [NAME] Start one unit and stop all others\n"
3955 " kill [NAME...] Send signal to processes of a unit\n"
3956 " is-active [NAME...] Check whether units are active\n"
3957 " status [NAME...|PID...] Show runtime status of one or more units\n"
3958 " show [NAME...|JOB...] Show properties of one or more\n"
3959 " units/jobs or the manager\n"
3960 " help [NAME...|PID...] Show manual for one or more units\n"
3961 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3963 " load [NAME...] Load one or more units\n\n"
3964 "Unit File Commands:\n"
3965 " list-unit-files List installed unit files\n"
3966 " enable [NAME...] Enable one or more unit files\n"
3967 " disable [NAME...] Disable one or more unit files\n"
3968 " reenable [NAME...] Reenable one or more unit files\n"
3969 " preset [NAME...] Enable/disable one or more unit files\n"
3970 " based on preset configuration\n"
3971 " mask [NAME...] Mask one or more units\n"
3972 " unmask [NAME...] Unmask one or more units\n"
3973 " link [PATH...] Link one or more units files into\n"
3974 " the search path\n"
3975 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3977 " list-jobs List jobs\n"
3978 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3979 "Status Commands:\n"
3980 " dump Dump server status\n"
3981 " dot Dump dependency graph for dot(1)\n\n"
3982 "Snapshot Commands:\n"
3983 " snapshot [NAME] Create a snapshot\n"
3984 " delete [NAME...] Remove one or more snapshots\n\n"
3985 "Environment Commands:\n"
3986 " show-environment Dump environment\n"
3987 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3988 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3989 "Manager Lifecycle Commands:\n"
3990 " daemon-reload Reload systemd manager configuration\n"
3991 " daemon-reexec Reexecute systemd manager\n\n"
3992 "System Commands:\n"
3993 " default Enter system default mode\n"
3994 " rescue Enter system rescue mode\n"
3995 " emergency Enter system emergency mode\n"
3996 " halt Shut down and halt the system\n"
3997 " poweroff Shut down and power-off the system\n"
3998 " reboot Shut down and reboot the system\n"
3999 " kexec Shut down and reboot the system with kexec\n"
4000 " exit Request user instance exit\n"
4001 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4002 " suspend Suspend the system\n"
4003 " hibernate Hibernate the system\n",
4004 program_invocation_short_name);
4009 static int halt_help(void) {
4011 printf("%s [OPTIONS...]\n\n"
4012 "%s the system.\n\n"
4013 " --help Show this help\n"
4014 " --halt Halt the machine\n"
4015 " -p --poweroff Switch off the machine\n"
4016 " --reboot Reboot the machine\n"
4017 " -f --force Force immediate halt/power-off/reboot\n"
4018 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4019 " -d --no-wtmp Don't write wtmp record\n"
4020 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4021 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4022 program_invocation_short_name,
4023 arg_action == ACTION_REBOOT ? "Reboot" :
4024 arg_action == ACTION_POWEROFF ? "Power off" :
4030 static int shutdown_help(void) {
4032 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4033 "Shut down the system.\n\n"
4034 " --help Show this help\n"
4035 " -H --halt Halt the machine\n"
4036 " -P --poweroff Power-off the machine\n"
4037 " -r --reboot Reboot the machine\n"
4038 " -h Equivalent to --poweroff, overridden by --halt\n"
4039 " -k Don't halt/power-off/reboot, just send warnings\n"
4040 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4041 " -c Cancel a pending shutdown\n",
4042 program_invocation_short_name);
4047 static int telinit_help(void) {
4049 printf("%s [OPTIONS...] {COMMAND}\n\n"
4050 "Send control commands to the init daemon.\n\n"
4051 " --help Show this help\n"
4052 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4054 " 0 Power-off the machine\n"
4055 " 6 Reboot the machine\n"
4056 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4057 " 1, s, S Enter rescue mode\n"
4058 " q, Q Reload init daemon configuration\n"
4059 " u, U Reexecute init daemon\n",
4060 program_invocation_short_name);
4065 static int runlevel_help(void) {
4067 printf("%s [OPTIONS...]\n\n"
4068 "Prints the previous and current runlevel of the init system.\n\n"
4069 " --help Show this help\n",
4070 program_invocation_short_name);
4075 static int systemctl_parse_argv(int argc, char *argv[]) {
4079 ARG_IGNORE_DEPENDENCIES,
4094 ARG_NO_ASK_PASSWORD,
4101 static const struct option options[] = {
4102 { "help", no_argument, NULL, 'h' },
4103 { "version", no_argument, NULL, ARG_VERSION },
4104 { "type", required_argument, NULL, 't' },
4105 { "property", required_argument, NULL, 'p' },
4106 { "all", no_argument, NULL, 'a' },
4107 { "failed", no_argument, NULL, ARG_FAILED },
4108 { "full", no_argument, NULL, ARG_FULL },
4109 { "fail", no_argument, NULL, ARG_FAIL },
4110 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4111 { "user", no_argument, NULL, ARG_USER },
4112 { "system", no_argument, NULL, ARG_SYSTEM },
4113 { "global", no_argument, NULL, ARG_GLOBAL },
4114 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4115 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4116 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4117 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4118 { "quiet", no_argument, NULL, 'q' },
4119 { "order", no_argument, NULL, ARG_ORDER },
4120 { "require", no_argument, NULL, ARG_REQUIRE },
4121 { "root", required_argument, NULL, ARG_ROOT },
4122 { "force", no_argument, NULL, ARG_FORCE },
4123 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4124 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4125 { "signal", required_argument, NULL, 's' },
4126 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4127 { "host", required_argument, NULL, 'H' },
4128 { "privileged",no_argument, NULL, 'P' },
4129 { "runtime", no_argument, NULL, ARG_RUNTIME },
4130 { "lines", required_argument, NULL, 'n' },
4131 { "follow", no_argument, NULL, ARG_FOLLOW },
4132 { "output", required_argument, NULL, 'o' },
4133 { NULL, 0, NULL, 0 }
4141 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4150 puts(PACKAGE_STRING);
4152 puts(SYSTEMD_FEATURES);
4156 if (unit_type_from_string(optarg) >= 0) {
4160 if (unit_load_state_from_string(optarg) >= 0) {
4161 arg_load_state = optarg;
4164 log_error("Unkown unit type or load state '%s'.",
4170 if (!(l = strv_append(arg_property, optarg)))
4173 strv_free(arg_property);
4176 /* If the user asked for a particular
4177 * property, show it to him, even if it is
4188 arg_job_mode = "fail";
4191 case ARG_IGNORE_DEPENDENCIES:
4192 arg_job_mode = "ignore-dependencies";
4196 arg_scope = UNIT_FILE_USER;
4200 arg_scope = UNIT_FILE_SYSTEM;
4204 arg_scope = UNIT_FILE_GLOBAL;
4208 arg_no_block = true;
4212 arg_no_legend = true;
4216 arg_no_pager = true;
4224 arg_dot = DOT_ORDER;
4228 arg_dot = DOT_REQUIRE;
4256 /* -f is short for both --follow and --force! */
4262 arg_no_reload = true;
4266 arg_kill_who = optarg;
4270 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4271 log_error("Failed to parse signal string %s.", optarg);
4276 case ARG_NO_ASK_PASSWORD:
4277 arg_ask_password = false;
4281 arg_transport = TRANSPORT_POLKIT;
4285 arg_transport = TRANSPORT_SSH;
4294 if (safe_atou(optarg, &arg_lines) < 0) {
4295 log_error("Failed to parse lines '%s'", optarg);
4301 arg_output = output_mode_from_string(optarg);
4302 if (arg_output < 0) {
4303 log_error("Unknown output '%s'.", optarg);
4312 log_error("Unknown option code '%c'.", c);
4317 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4318 log_error("Cannot access user instance remotely.");
4325 static int halt_parse_argv(int argc, char *argv[]) {
4334 static const struct option options[] = {
4335 { "help", no_argument, NULL, ARG_HELP },
4336 { "halt", no_argument, NULL, ARG_HALT },
4337 { "poweroff", no_argument, NULL, 'p' },
4338 { "reboot", no_argument, NULL, ARG_REBOOT },
4339 { "force", no_argument, NULL, 'f' },
4340 { "wtmp-only", no_argument, NULL, 'w' },
4341 { "no-wtmp", no_argument, NULL, 'd' },
4342 { "no-sync", no_argument, NULL, 'n' },
4343 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4344 { NULL, 0, NULL, 0 }
4352 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4353 if (runlevel == '0' || runlevel == '6')
4356 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4364 arg_action = ACTION_HALT;
4368 if (arg_action != ACTION_REBOOT)
4369 arg_action = ACTION_POWEROFF;
4373 arg_action = ACTION_REBOOT;
4398 /* Compatibility nops */
4405 log_error("Unknown option code '%c'.", c);
4410 if (optind < argc) {
4411 log_error("Too many arguments.");
4418 static int parse_time_spec(const char *t, usec_t *_u) {
4422 if (streq(t, "now"))
4424 else if (!strchr(t, ':')) {
4427 if (safe_atou64(t, &u) < 0)
4430 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4439 hour = strtol(t, &e, 10);
4440 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4443 minute = strtol(e+1, &e, 10);
4444 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4447 n = now(CLOCK_REALTIME);
4448 s = (time_t) (n / USEC_PER_SEC);
4451 assert_se(localtime_r(&s, &tm));
4453 tm.tm_hour = (int) hour;
4454 tm.tm_min = (int) minute;
4457 assert_se(s = mktime(&tm));
4459 *_u = (usec_t) s * USEC_PER_SEC;
4462 *_u += USEC_PER_DAY;
4468 static int shutdown_parse_argv(int argc, char *argv[]) {
4475 static const struct option options[] = {
4476 { "help", no_argument, NULL, ARG_HELP },
4477 { "halt", no_argument, NULL, 'H' },
4478 { "poweroff", no_argument, NULL, 'P' },
4479 { "reboot", no_argument, NULL, 'r' },
4480 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4481 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4482 { NULL, 0, NULL, 0 }
4490 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4498 arg_action = ACTION_HALT;
4502 arg_action = ACTION_POWEROFF;
4507 arg_action = ACTION_KEXEC;
4509 arg_action = ACTION_REBOOT;
4513 arg_action = ACTION_KEXEC;
4517 if (arg_action != ACTION_HALT)
4518 arg_action = ACTION_POWEROFF;
4531 /* Compatibility nops */
4535 arg_action = ACTION_CANCEL_SHUTDOWN;
4542 log_error("Unknown option code '%c'.", c);
4547 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4548 r = parse_time_spec(argv[optind], &arg_when);
4550 log_error("Failed to parse time specification: %s", argv[optind]);
4554 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4556 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4557 /* No time argument for shutdown cancel */
4558 arg_wall = argv + optind;
4559 else if (argc > optind + 1)
4560 /* We skip the time argument */
4561 arg_wall = argv + optind + 1;
4568 static int telinit_parse_argv(int argc, char *argv[]) {
4575 static const struct option options[] = {
4576 { "help", no_argument, NULL, ARG_HELP },
4577 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4578 { NULL, 0, NULL, 0 }
4581 static const struct {
4585 { '0', ACTION_POWEROFF },
4586 { '6', ACTION_REBOOT },
4587 { '1', ACTION_RESCUE },
4588 { '2', ACTION_RUNLEVEL2 },
4589 { '3', ACTION_RUNLEVEL3 },
4590 { '4', ACTION_RUNLEVEL4 },
4591 { '5', ACTION_RUNLEVEL5 },
4592 { 's', ACTION_RESCUE },
4593 { 'S', ACTION_RESCUE },
4594 { 'q', ACTION_RELOAD },
4595 { 'Q', ACTION_RELOAD },
4596 { 'u', ACTION_REEXEC },
4597 { 'U', ACTION_REEXEC }
4606 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4621 log_error("Unknown option code '%c'.", c);
4626 if (optind >= argc) {
4631 if (optind + 1 < argc) {
4632 log_error("Too many arguments.");
4636 if (strlen(argv[optind]) != 1) {
4637 log_error("Expected single character argument.");
4641 for (i = 0; i < ELEMENTSOF(table); i++)
4642 if (table[i].from == argv[optind][0])
4645 if (i >= ELEMENTSOF(table)) {
4646 log_error("Unknown command '%s'.", argv[optind]);
4650 arg_action = table[i].to;
4657 static int runlevel_parse_argv(int argc, char *argv[]) {
4663 static const struct option options[] = {
4664 { "help", no_argument, NULL, ARG_HELP },
4665 { NULL, 0, NULL, 0 }
4673 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4684 log_error("Unknown option code '%c'.", c);
4689 if (optind < argc) {
4690 log_error("Too many arguments.");
4697 static int parse_argv(int argc, char *argv[]) {
4701 if (program_invocation_short_name) {
4703 if (strstr(program_invocation_short_name, "halt")) {
4704 arg_action = ACTION_HALT;
4705 return halt_parse_argv(argc, argv);
4706 } else if (strstr(program_invocation_short_name, "poweroff")) {
4707 arg_action = ACTION_POWEROFF;
4708 return halt_parse_argv(argc, argv);
4709 } else if (strstr(program_invocation_short_name, "reboot")) {
4711 arg_action = ACTION_KEXEC;
4713 arg_action = ACTION_REBOOT;
4714 return halt_parse_argv(argc, argv);
4715 } else if (strstr(program_invocation_short_name, "shutdown")) {
4716 arg_action = ACTION_POWEROFF;
4717 return shutdown_parse_argv(argc, argv);
4718 } else if (strstr(program_invocation_short_name, "init")) {
4720 if (sd_booted() > 0) {
4721 arg_action = ACTION_INVALID;
4722 return telinit_parse_argv(argc, argv);
4724 /* Hmm, so some other init system is
4725 * running, we need to forward this
4726 * request to it. For now we simply
4727 * guess that it is Upstart. */
4729 execv("/lib/upstart/telinit", argv);
4731 log_error("Couldn't find an alternative telinit implementation to spawn.");
4735 } else if (strstr(program_invocation_short_name, "runlevel")) {
4736 arg_action = ACTION_RUNLEVEL;
4737 return runlevel_parse_argv(argc, argv);
4741 arg_action = ACTION_SYSTEMCTL;
4742 return systemctl_parse_argv(argc, argv);
4745 static int action_to_runlevel(void) {
4747 static const char table[_ACTION_MAX] = {
4748 [ACTION_HALT] = '0',
4749 [ACTION_POWEROFF] = '0',
4750 [ACTION_REBOOT] = '6',
4751 [ACTION_RUNLEVEL2] = '2',
4752 [ACTION_RUNLEVEL3] = '3',
4753 [ACTION_RUNLEVEL4] = '4',
4754 [ACTION_RUNLEVEL5] = '5',
4755 [ACTION_RESCUE] = '1'
4758 assert(arg_action < _ACTION_MAX);
4760 return table[arg_action];
4763 static int talk_upstart(void) {
4764 DBusMessage *m = NULL, *reply = NULL;
4766 int previous, rl, r;
4768 env1_buf[] = "RUNLEVEL=X",
4769 env2_buf[] = "PREVLEVEL=X";
4770 char *env1 = env1_buf, *env2 = env2_buf;
4771 const char *emit = "runlevel";
4772 dbus_bool_t b_false = FALSE;
4773 DBusMessageIter iter, sub;
4774 DBusConnection *bus;
4776 dbus_error_init(&error);
4778 if (!(rl = action_to_runlevel()))
4781 if (utmp_get_runlevel(&previous, NULL) < 0)
4784 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4785 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4790 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4795 if ((r = bus_check_peercred(bus)) < 0) {
4796 log_error("Failed to verify owner of bus.");
4800 if (!(m = dbus_message_new_method_call(
4801 "com.ubuntu.Upstart",
4802 "/com/ubuntu/Upstart",
4803 "com.ubuntu.Upstart0_6",
4806 log_error("Could not allocate message.");
4811 dbus_message_iter_init_append(m, &iter);
4813 env1_buf[sizeof(env1_buf)-2] = rl;
4814 env2_buf[sizeof(env2_buf)-2] = previous;
4816 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4817 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4818 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4819 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4820 !dbus_message_iter_close_container(&iter, &sub) ||
4821 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4822 log_error("Could not append arguments to message.");
4827 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4829 if (error_is_no_service(&error)) {
4834 log_error("Failed to issue method call: %s", bus_error_message(&error));
4843 dbus_message_unref(m);
4846 dbus_message_unref(reply);
4849 dbus_connection_flush(bus);
4850 dbus_connection_close(bus);
4851 dbus_connection_unref(bus);
4854 dbus_error_free(&error);
4859 static int talk_initctl(void) {
4860 struct init_request request;
4864 if (!(rl = action_to_runlevel()))
4868 request.magic = INIT_MAGIC;
4869 request.sleeptime = 0;
4870 request.cmd = INIT_CMD_RUNLVL;
4871 request.runlevel = rl;
4873 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4875 if (errno == ENOENT)
4878 log_error("Failed to open "INIT_FIFO": %m");
4883 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4884 close_nointr_nofail(fd);
4887 log_error("Failed to write to "INIT_FIFO": %m");
4888 return errno ? -errno : -EIO;
4894 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4896 static const struct {
4904 int (* const dispatch)(DBusConnection *bus, char **args);
4906 { "list-units", LESS, 1, list_units },
4907 { "list-unit-files", EQUAL, 1, list_unit_files },
4908 { "list-jobs", EQUAL, 1, list_jobs },
4909 { "clear-jobs", EQUAL, 1, daemon_reload },
4910 { "load", MORE, 2, load_unit },
4911 { "cancel", MORE, 2, cancel_job },
4912 { "start", MORE, 2, start_unit },
4913 { "stop", MORE, 2, start_unit },
4914 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4915 { "reload", MORE, 2, start_unit },
4916 { "restart", MORE, 2, start_unit },
4917 { "try-restart", MORE, 2, start_unit },
4918 { "reload-or-restart", MORE, 2, start_unit },
4919 { "reload-or-try-restart", MORE, 2, start_unit },
4920 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4921 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4922 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4923 { "isolate", EQUAL, 2, start_unit },
4924 { "kill", MORE, 2, kill_unit },
4925 { "is-active", MORE, 2, check_unit },
4926 { "check", MORE, 2, check_unit },
4927 { "show", MORE, 1, show },
4928 { "status", MORE, 2, show },
4929 { "help", MORE, 2, show },
4930 { "dump", EQUAL, 1, dump },
4931 { "dot", EQUAL, 1, dot },
4932 { "snapshot", LESS, 2, snapshot },
4933 { "delete", MORE, 2, delete_snapshot },
4934 { "daemon-reload", EQUAL, 1, daemon_reload },
4935 { "daemon-reexec", EQUAL, 1, daemon_reload },
4936 { "show-environment", EQUAL, 1, show_enviroment },
4937 { "set-environment", MORE, 2, set_environment },
4938 { "unset-environment", MORE, 2, set_environment },
4939 { "halt", EQUAL, 1, start_special },
4940 { "poweroff", EQUAL, 1, start_special },
4941 { "reboot", EQUAL, 1, start_special },
4942 { "kexec", EQUAL, 1, start_special },
4943 { "suspend", EQUAL, 1, start_special },
4944 { "hibernate", EQUAL, 1, start_special },
4945 { "default", EQUAL, 1, start_special },
4946 { "rescue", EQUAL, 1, start_special },
4947 { "emergency", EQUAL, 1, start_special },
4948 { "exit", EQUAL, 1, start_special },
4949 { "reset-failed", MORE, 1, reset_failed },
4950 { "enable", MORE, 2, enable_unit },
4951 { "disable", MORE, 2, enable_unit },
4952 { "is-enabled", MORE, 2, unit_is_enabled },
4953 { "reenable", MORE, 2, enable_unit },
4954 { "preset", MORE, 2, enable_unit },
4955 { "mask", MORE, 2, enable_unit },
4956 { "unmask", MORE, 2, enable_unit },
4957 { "link", MORE, 2, enable_unit },
4958 { "switch-root", MORE, 2, switch_root },
4968 left = argc - optind;
4971 /* Special rule: no arguments means "list-units" */
4974 if (streq(argv[optind], "help") && !argv[optind+1]) {
4975 log_error("This command expects one or more "
4976 "unit names. Did you mean --help?");
4980 for (i = 0; i < ELEMENTSOF(verbs); i++)
4981 if (streq(argv[optind], verbs[i].verb))
4984 if (i >= ELEMENTSOF(verbs)) {
4985 log_error("Unknown operation '%s'.", argv[optind]);
4990 switch (verbs[i].argc_cmp) {
4993 if (left != verbs[i].argc) {
4994 log_error("Invalid number of arguments.");
5001 if (left < verbs[i].argc) {
5002 log_error("Too few arguments.");
5009 if (left > verbs[i].argc) {
5010 log_error("Too many arguments.");
5017 assert_not_reached("Unknown comparison operator.");
5020 /* Require a bus connection for all operations but
5022 if (!streq(verbs[i].verb, "enable") &&
5023 !streq(verbs[i].verb, "disable") &&
5024 !streq(verbs[i].verb, "is-enabled") &&
5025 !streq(verbs[i].verb, "list-unit-files") &&
5026 !streq(verbs[i].verb, "reenable") &&
5027 !streq(verbs[i].verb, "preset") &&
5028 !streq(verbs[i].verb, "mask") &&
5029 !streq(verbs[i].verb, "unmask") &&
5030 !streq(verbs[i].verb, "link")) {
5032 if (running_in_chroot() > 0) {
5033 log_info("Running in chroot, ignoring request.");
5037 if (((!streq(verbs[i].verb, "reboot") &&
5038 !streq(verbs[i].verb, "halt") &&
5039 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5040 log_error("Failed to get D-Bus connection: %s",
5041 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5047 if (!bus && !avoid_bus()) {
5048 log_error("Failed to get D-Bus connection: %s",
5049 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5054 return verbs[i].dispatch(bus, argv + optind);
5057 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5059 struct msghdr msghdr;
5060 struct iovec iovec[2];
5061 union sockaddr_union sockaddr;
5062 struct sd_shutdown_command c;
5064 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5071 c.dry_run = dry_run;
5075 sockaddr.sa.sa_family = AF_UNIX;
5076 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5079 msghdr.msg_name = &sockaddr;
5080 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5083 iovec[0].iov_base = (char*) &c;
5084 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5086 if (isempty(message))
5087 msghdr.msg_iovlen = 1;
5089 iovec[1].iov_base = (char*) message;
5090 iovec[1].iov_len = strlen(message);
5091 msghdr.msg_iovlen = 2;
5093 msghdr.msg_iov = iovec;
5095 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5096 close_nointr_nofail(fd);
5100 close_nointr_nofail(fd);
5104 static int reload_with_fallback(DBusConnection *bus) {
5107 /* First, try systemd via D-Bus. */
5108 if (daemon_reload(bus, NULL) >= 0)
5112 /* Nothing else worked, so let's try signals */
5113 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5115 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5116 log_error("kill() failed: %m");
5123 static int start_with_fallback(DBusConnection *bus) {
5126 /* First, try systemd via D-Bus. */
5127 if (start_unit(bus, NULL) >= 0)
5131 /* Hmm, talking to systemd via D-Bus didn't work. Then
5132 * let's try to talk to Upstart via D-Bus. */
5133 if (talk_upstart() > 0)
5136 /* Nothing else worked, so let's try
5138 if (talk_initctl() > 0)
5141 log_error("Failed to talk to init daemon.");
5145 warn_wall(arg_action);
5149 static _noreturn_ void halt_now(enum action a) {
5151 /* Make sure C-A-D is handled by the kernel from this
5153 reboot(RB_ENABLE_CAD);
5158 log_info("Halting.");
5159 reboot(RB_HALT_SYSTEM);
5162 case ACTION_POWEROFF:
5163 log_info("Powering off.");
5164 reboot(RB_POWER_OFF);
5168 log_info("Rebooting.");
5169 reboot(RB_AUTOBOOT);
5173 assert_not_reached("Unknown halt action.");
5176 assert_not_reached("Uh? This shouldn't happen.");
5179 static int halt_main(DBusConnection *bus) {
5182 if (geteuid() != 0) {
5183 /* Try logind if we are a normal user and no special
5184 * mode applies. Maybe PolicyKit allows us to shutdown
5187 if (arg_when <= 0 &&
5190 (arg_action == ACTION_POWEROFF ||
5191 arg_action == ACTION_REBOOT)) {
5192 r = reboot_with_logind(bus, arg_action);
5197 log_error("Must be root.");
5204 m = strv_join(arg_wall, " ");
5205 r = send_shutdownd(arg_when,
5206 arg_action == ACTION_HALT ? 'H' :
5207 arg_action == ACTION_POWEROFF ? 'P' :
5208 arg_action == ACTION_KEXEC ? 'K' :
5216 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5218 char date[FORMAT_TIMESTAMP_MAX];
5220 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5221 format_timestamp(date, sizeof(date), arg_when));
5226 if (!arg_dry && !arg_force)
5227 return start_with_fallback(bus);
5230 if (sd_booted() > 0)
5231 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5233 r = utmp_put_shutdown();
5235 log_warning("Failed to write utmp record: %s", strerror(-r));
5245 halt_now(arg_action);
5246 /* We should never reach this. */
5250 static int runlevel_main(void) {
5251 int r, runlevel, previous;
5253 r = utmp_get_runlevel(&runlevel, &previous);
5260 previous <= 0 ? 'N' : previous,
5261 runlevel <= 0 ? 'N' : runlevel);
5266 int main(int argc, char*argv[]) {
5267 int r, retval = EXIT_FAILURE;
5268 DBusConnection *bus = NULL;
5271 dbus_error_init(&error);
5273 log_parse_environment();
5276 r = parse_argv(argc, argv);
5280 retval = EXIT_SUCCESS;
5284 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5285 * let's shortcut this */
5286 if (arg_action == ACTION_RUNLEVEL) {
5287 r = runlevel_main();
5288 retval = r < 0 ? EXIT_FAILURE : r;
5292 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5293 log_info("Running in chroot, ignoring request.");
5299 if (arg_transport == TRANSPORT_NORMAL)
5300 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5301 else if (arg_transport == TRANSPORT_POLKIT) {
5302 bus_connect_system_polkit(&bus, &error);
5303 private_bus = false;
5304 } else if (arg_transport == TRANSPORT_SSH) {
5305 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5306 private_bus = false;
5308 assert_not_reached("Uh, invalid transport...");
5311 switch (arg_action) {
5313 case ACTION_SYSTEMCTL:
5314 r = systemctl_main(bus, argc, argv, &error);
5318 case ACTION_POWEROFF:
5324 case ACTION_RUNLEVEL2:
5325 case ACTION_RUNLEVEL3:
5326 case ACTION_RUNLEVEL4:
5327 case ACTION_RUNLEVEL5:
5329 case ACTION_EMERGENCY:
5330 case ACTION_DEFAULT:
5331 r = start_with_fallback(bus);
5336 r = reload_with_fallback(bus);
5339 case ACTION_CANCEL_SHUTDOWN: {
5343 m = strv_join(arg_wall, " ");
5345 retval = EXIT_FAILURE;
5349 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5351 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5356 case ACTION_INVALID:
5357 case ACTION_RUNLEVEL:
5359 assert_not_reached("Unknown action");
5362 retval = r < 0 ? EXIT_FAILURE : r;
5366 dbus_connection_flush(bus);
5367 dbus_connection_close(bus);
5368 dbus_connection_unref(bus);
5371 dbus_error_free(&error);
5375 strv_free(arg_property);
5378 ask_password_agent_close();
5379 polkit_agent_close();