]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/systemctl/systemctl.c
Merge pull request #1227 from intelfx/systemctl-legacy-tools-polkit
[thirdparty/systemd.git] / src / systemctl / systemctl.c
index 538838b7fce42b49feece114df434c0391b8aa15..d21ba9a56665444f1ab7d5cd4122e7c8a1ec4c42 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/reboot.h>
-#include <linux/reboot.h>
-#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <getopt.h>
+#include <linux/reboot.h>
 #include <locale.h>
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
 #include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
+#include <sys/reboot.h>
 #include <sys/socket.h>
-#include <stddef.h>
+#include <unistd.h>
 
+#include "sd-bus.h"
 #include "sd-daemon.h"
 #include "sd-login.h"
-#include "sd-bus.h"
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-#include "set.h"
-#include "utmp-wtmp.h"
-#include "special.h"
-#include "initreq.h"
-#include "path-util.h"
-#include "strv.h"
+
+#include "build.h"
+#include "bus-common-errors.h"
+#include "bus-error.h"
+#include "bus-message.h"
+#include "bus-util.h"
 #include "cgroup-show.h"
 #include "cgroup-util.h"
-#include "list.h"
-#include "path-lookup.h"
-#include "exit-status.h"
-#include "build.h"
-#include "unit-name.h"
-#include "pager.h"
-#include "spawn-ask-password-agent.h"
-#include "spawn-polkit-agent.h"
-#include "install.h"
-#include "logs-show.h"
-#include "socket-util.h"
-#include "fileio.h"
 #include "copy.h"
-#include "env-util.h"
-#include "bus-util.h"
-#include "bus-message.h"
-#include "bus-error.h"
-#include "bus-common-errors.h"
-#include "mkdir.h"
 #include "dropin.h"
 #include "efivars.h"
+#include "env-util.h"
+#include "exit-status.h"
+#include "fileio.h"
 #include "formats-util.h"
-#include "process-util.h"
-#include "terminal-util.h"
 #include "hostname-util.h"
+#include "initreq.h"
+#include "install.h"
+#include "list.h"
+#include "log.h"
+#include "logs-show.h"
+#include "macro.h"
+#include "mkdir.h"
+#include "pager.h"
+#include "path-lookup.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "set.h"
 #include "signal-util.h"
+#include "socket-util.h"
+#include "spawn-ask-password-agent.h"
+#include "spawn-polkit-agent.h"
+#include "special.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "unit-name.h"
+#include "util.h"
+#include "utmp-wtmp.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
@@ -100,7 +101,7 @@ static bool arg_quiet = false;
 static bool arg_full = false;
 static bool arg_recursive = false;
 static int arg_force = 0;
-static bool arg_ask_password = true;
+static bool arg_ask_password = false;
 static bool arg_runtime = false;
 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
 static char **arg_wall = NULL;
@@ -535,10 +536,8 @@ static int get_unit_list(
                 return bus_log_create_error(r);
 
         r = sd_bus_call(bus, m, 0, &error, &reply);
-        if (r < 0) {
-                log_error("Failed to list units: %s", bus_error_message(&error, r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
 
         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
         if (r < 0)
@@ -605,7 +604,7 @@ static int get_unit_list_recursive(
         r = set_put(replies, reply);
         if (r < 0) {
                 sd_bus_message_unref(reply);
-                return r;
+                return log_oom();
         }
 
         if (arg_recursive) {
@@ -614,15 +613,15 @@ static int get_unit_list_recursive(
 
                 r = sd_get_machine_names(&machines);
                 if (r < 0)
-                        return r;
+                        return log_error_errno(r, "Failed to get machine names: %m");
 
                 STRV_FOREACH(i, machines) {
-                        _cleanup_bus_close_unref_ sd_bus *container = NULL;
+                        _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
                         int k;
 
                         r = sd_bus_open_system_machine(&container, *i);
                         if (r < 0) {
-                                log_error_errno(r, "Failed to connect to container %s: %m", *i);
+                                log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i);
                                 continue;
                         }
 
@@ -635,7 +634,7 @@ static int get_unit_list_recursive(
                         r = set_put(replies, reply);
                         if (r < 0) {
                                 sd_bus_message_unref(reply);
-                                return r;
+                                return log_oom();
                         }
                 }
 
@@ -1301,10 +1300,11 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
                 const char *on, *off;
                 const char *id;
 
-                if (u->state == UNIT_FILE_MASKED ||
-                    u->state == UNIT_FILE_MASKED_RUNTIME ||
-                    u->state == UNIT_FILE_DISABLED ||
-                    u->state == UNIT_FILE_INVALID) {
+                if (IN_SET(u->state,
+                           UNIT_FILE_MASKED,
+                           UNIT_FILE_MASKED_RUNTIME,
+                           UNIT_FILE_DISABLED,
+                           UNIT_FILE_INVALID)) {
                         on  = ansi_highlight_red();
                         off = ansi_highlight_off();
                 } else if (u->state == UNIT_FILE_ENABLED) {
@@ -1474,9 +1474,12 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha
                                        "Requisite\0"
                                        "RequisiteOverridable\0"
                                        "Wants\0"
+                                       "ConsistsOf\0"
                                        "BindsTo\0",
                 [DEPENDENCY_REVERSE] = "RequiredBy\0"
                                        "RequiredByOverridable\0"
+                                       "RequisiteOf\0"
+                                       "RequisiteOfOverridable\0"
                                        "WantedBy\0"
                                        "PartOf\0"
                                        "BoundBy\0",
@@ -1709,7 +1712,7 @@ static int compare_machine_info(const void *a, const void *b) {
 }
 
 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
-        _cleanup_bus_close_unref_ sd_bus *container = NULL;
+        _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
         int r;
 
         assert(mi);
@@ -1743,7 +1746,7 @@ static int get_machine_list(
         _cleanup_free_ char *hn = NULL;
         size_t sz = 0;
         char **i;
-        int c = 0;
+        int c = 0, r;
 
         hn = gethostname_malloc();
         if (!hn)
@@ -1761,7 +1764,10 @@ static int get_machine_list(
                 c++;
         }
 
-        sd_get_machine_names(&m);
+        r = sd_get_machine_names(&m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get machine list: %m");
+
         STRV_FOREACH(i, m) {
                 _cleanup_free_ char *class = NULL;
 
@@ -2760,7 +2766,7 @@ static int start_unit(sd_bus *bus, char **args) {
 static int reboot_with_logind(sd_bus *bus, enum action a) {
 #ifdef HAVE_LOGIND
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        const char *method;
+        const char *method, *description;
         int r;
 
         if (!bus)
@@ -2772,28 +2778,60 @@ static int reboot_with_logind(sd_bus *bus, enum action a) {
 
         case ACTION_REBOOT:
                 method = "Reboot";
+                description = "reboot system";
                 break;
 
         case ACTION_POWEROFF:
                 method = "PowerOff";
+                description = "power off system";
                 break;
 
         case ACTION_SUSPEND:
                 method = "Suspend";
+                description = "suspend system";
                 break;
 
         case ACTION_HIBERNATE:
                 method = "Hibernate";
+                description = "hibernate system";
                 break;
 
         case ACTION_HYBRID_SLEEP:
                 method = "HybridSleep";
+                description = "put system into hybrid sleep";
                 break;
 
         default:
                 return -EINVAL;
         }
 
+        if (!strv_isempty(arg_wall)) {
+                _cleanup_free_ char *m;
+
+                m = strv_join(arg_wall, " ");
+                if (!m)
+                        return log_oom();
+
+                r = sd_bus_call_method(
+                               bus,
+                               "org.freedesktop.login1",
+                               "/org/freedesktop/login1",
+                               "org.freedesktop.login1.Manager",
+                               "SetWallMessage",
+                               &error,
+                               NULL,
+                               "sb",
+                               m,
+                               !arg_no_wall);
+
+                if (r < 0) {
+                        log_warning_errno(r, "Failed to set wall message, ignoring: %s",
+                                          bus_error_message(&error, r));
+                        sd_bus_error_free(&error);
+                }
+        }
+
+
         r = sd_bus_call_method(
                         bus,
                         "org.freedesktop.login1",
@@ -2804,7 +2842,7 @@ static int reboot_with_logind(sd_bus *bus, enum action a) {
                         NULL,
                         "b", arg_ask_password);
         if (r < 0)
-                log_error("Failed to execute operation: %s", bus_error_message(&error, r));
+                log_error("Failed to %s via logind: %s", description, bus_error_message(&error, r));
 
         return r;
 #else
@@ -2869,10 +2907,11 @@ static int check_inhibitors(sd_bus *bus, enum action a) {
                         return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
 
                 if (!strv_contains(sv,
-                                  a == ACTION_HALT ||
-                                  a == ACTION_POWEROFF ||
-                                  a == ACTION_REBOOT ||
-                                  a == ACTION_KEXEC ? "shutdown" : "sleep"))
+                                   IN_SET(a,
+                                          ACTION_HALT,
+                                          ACTION_POWEROFF,
+                                          ACTION_REBOOT,
+                                          ACTION_KEXEC) ? "shutdown" : "sleep"))
                         continue;
 
                 get_process_comm(pid, &comm);
@@ -2993,29 +3032,36 @@ static int start_special(sd_bus *bus, char **args) {
         }
 
         if (arg_force >= 2 &&
-            (a == ACTION_HALT ||
-             a == ACTION_POWEROFF ||
-             a == ACTION_REBOOT))
+            IN_SET(a,
+                   ACTION_HALT,
+                   ACTION_POWEROFF,
+                   ACTION_REBOOT))
                 return halt_now(a);
 
         if (arg_force >= 1 &&
-            (a == ACTION_HALT ||
-             a == ACTION_POWEROFF ||
-             a == ACTION_REBOOT ||
-             a == ACTION_KEXEC ||
-             a == ACTION_EXIT))
+            IN_SET(a,
+                   ACTION_HALT,
+                   ACTION_POWEROFF,
+                   ACTION_REBOOT,
+                   ACTION_KEXEC,
+                   ACTION_EXIT))
                 return daemon_reload(bus, args);
 
         /* first try logind, to allow authentication with polkit */
         if (geteuid() != 0 &&
-            (a == ACTION_POWEROFF ||
-             a == ACTION_REBOOT ||
-             a == ACTION_SUSPEND ||
-             a == ACTION_HIBERNATE ||
-             a == ACTION_HYBRID_SLEEP)) {
+            IN_SET(a,
+                   ACTION_POWEROFF,
+                   ACTION_REBOOT,
+                   ACTION_SUSPEND,
+                   ACTION_HIBERNATE,
+                   ACTION_HYBRID_SLEEP)) {
                 r = reboot_with_logind(bus, a);
-                if (r >= 0 || IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+                if (r >= 0)
+                        return r;
+                if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+                        /* requested operation is not supported or already in progress */
                         return r;
+                /* on all other errors, try low-level operation */
         }
 
         r = start_unit(bus, args);
@@ -3254,6 +3300,8 @@ typedef struct UnitStatusInfo {
         uint64_t memory_current;
         uint64_t memory_limit;
         uint64_t cpu_usage_nsec;
+        uint64_t tasks_current;
+        uint64_t tasks_max;
 
         LIST_HEAD(ExecStatusInfo, exec);
 } UnitStatusInfo;
@@ -3327,8 +3375,7 @@ static void print_status_info(
                         if (! dir || last) {
                                 printf(dir ? "        " : "  Drop-In: ");
 
-                                free(dir);
-                                dir = NULL;
+                                dir = mfree(dir);
 
                                 if (path_get_parent(*dropin, &dir) < 0) {
                                         log_oom();
@@ -3513,6 +3560,15 @@ static void print_status_info(
         if (i->status_errno > 0)
                 printf("    Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
 
+        if (i->tasks_current != (uint64_t) -1) {
+                printf("    Tasks: %" PRIu64, i->tasks_current);
+
+                if (i->tasks_max != (uint64_t) -1)
+                        printf(" (limit: %" PRIi64 ")\n", i->tasks_max);
+                else
+                        printf("\n");
+        }
+
         if (i->memory_current != (uint64_t) -1) {
                 char buf[FORMAT_BYTES_MAX];
 
@@ -3531,12 +3587,14 @@ static void print_status_info(
 
         if (i->control_group &&
             (i->main_pid > 0 || i->control_pid > 0 ||
-             ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
+             (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) {
                 unsigned c;
 
                 printf("   CGroup: %s\n", i->control_group);
 
-                if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
+                if (IN_SET(arg_transport,
+                           BUS_TRANSPORT_LOCAL,
+                           BUS_TRANSPORT_MACHINE)) {
                         unsigned k = 0;
                         pid_t extra[2];
                         static const char prefix[] = "           ";
@@ -3557,7 +3615,7 @@ static void print_status_info(
                 }
         }
 
-        if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
+        if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
                 show_journal_by_unit(
                                 stdout,
                                 i->id,
@@ -3570,7 +3628,6 @@ static void print_status_info(
                                 SD_JOURNAL_LOCAL_ONLY,
                                 arg_scope == UNIT_FILE_SYSTEM,
                                 ellipsized);
-        }
 
         if (i->need_daemon_reload)
                 warn_unit_file_changed(i->id);
@@ -3747,6 +3804,10 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
                         i->memory_current = u;
                 else if (streq(name, "MemoryLimit"))
                         i->memory_limit = u;
+                else if (streq(name, "TasksCurrent"))
+                        i->tasks_current = u;
+                else if (streq(name, "TasksMax"))
+                        i->tasks_max = u;
                 else if (streq(name, "CPUUsageNSec"))
                         i->cpu_usage_nsec = u;
 
@@ -4223,6 +4284,8 @@ static int show_one(
                 .memory_current = (uint64_t) -1,
                 .memory_limit = (uint64_t) -1,
                 .cpu_usage_nsec = (uint64_t) -1,
+                .tasks_current = (uint64_t) -1,
+                .tasks_max = (uint64_t) -1,
         };
         ExecStatusInfo *p;
         int r;
@@ -4241,10 +4304,8 @@ static int show_one(
                         &error,
                         &reply,
                         "s", "");
-        if (r < 0) {
-                log_error("Failed to get properties: %s", bus_error_message(&error, r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
 
         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
         if (r < 0)
@@ -4442,7 +4503,9 @@ static int show_system_status(sd_bus *bus) {
                format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
 
         printf("   CGroup: %s\n", mi.control_group ?: "/");
-        if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
+        if (IN_SET(arg_transport,
+                   BUS_TRANSPORT_LOCAL,
+                   BUS_TRANSPORT_MACHINE)) {
                 static const char prefix[] = "           ";
                 unsigned c;
 
@@ -4598,7 +4661,7 @@ static int cat_file(const char *filename, bool newline) {
                ansi_highlight_off());
         fflush(stdout);
 
-        return copy_bytes(fd, STDOUT_FILENO, (off_t) -1, false);
+        return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false);
 }
 
 static int cat(sd_bus *bus, char **args) {
@@ -5109,9 +5172,10 @@ static int enable_sysv_units(const char *verb, char **args) {
         if (arg_scope != UNIT_FILE_SYSTEM)
                 return 0;
 
-        if (!streq(verb, "enable") &&
-            !streq(verb, "disable") &&
-            !streq(verb, "is-enabled"))
+        if (!STR_IN_SET(verb,
+                        "enable",
+                        "disable",
+                        "is-enabled"))
                 return 0;
 
         /* Processes all SysV units, and reshuffles the array so that
@@ -5611,10 +5675,11 @@ static int unit_is_enabled(sd_bus *bus, char **args) {
                         if (state < 0)
                                 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
 
-                        if (state == UNIT_FILE_ENABLED ||
-                            state == UNIT_FILE_ENABLED_RUNTIME ||
-                            state == UNIT_FILE_STATIC ||
-                            state == UNIT_FILE_INDIRECT)
+                        if (IN_SET(state,
+                                   UNIT_FILE_ENABLED,
+                                   UNIT_FILE_ENABLED_RUNTIME,
+                                   UNIT_FILE_STATIC,
+                                   UNIT_FILE_INDIRECT))
                                 enabled = true;
 
                         if (!arg_quiet)
@@ -6261,6 +6326,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_PRESET_MODE,
                 ARG_FIRMWARE_SETUP,
                 ARG_NOW,
+                ARG_MESSAGE,
         };
 
         static const struct option options[] = {
@@ -6305,6 +6371,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "preset-mode",         required_argument, NULL, ARG_PRESET_MODE         },
                 { "firmware-setup",      no_argument,       NULL, ARG_FIRMWARE_SETUP      },
                 { "now",                 no_argument,       NULL, ARG_NOW                 },
+                { "message",             required_argument, NULL, ARG_MESSAGE             },
                 {}
         };
 
@@ -6313,6 +6380,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
+        /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
+        arg_ask_password = true;
+
         while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
 
                 switch (c) {
@@ -6589,6 +6659,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_now = true;
                         break;
 
+                case ARG_MESSAGE:
+                        if (strv_extend(&arg_wall, optarg) < 0)
+                                return log_oom();
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -7293,6 +7368,7 @@ static int halt_now(enum action a) {
                 reboot(RB_POWER_OFF);
                 return -errno;
 
+        case ACTION_KEXEC:
         case ACTION_REBOOT: {
                 _cleanup_free_ char *param = NULL;
 
@@ -7320,28 +7396,36 @@ static int halt_main(sd_bus *bus) {
                 return r;
 
         if (geteuid() != 0) {
+                if (arg_when > 0 ||
+                    arg_dry ||
+                    arg_force > 0) {
+                        log_error("Must be root.");
+                        return -EPERM;
+                }
+
                 /* Try logind if we are a normal user and no special
                  * mode applies. Maybe PolicyKit allows us to shutdown
                  * the machine. */
-
-                if (arg_when <= 0 &&
-                    !arg_dry &&
-                    arg_force <= 0 &&
-                    (arg_action == ACTION_POWEROFF ||
-                     arg_action == ACTION_REBOOT)) {
+                if (IN_SET(arg_action,
+                           ACTION_POWEROFF,
+                           ACTION_REBOOT)) {
                         r = reboot_with_logind(bus, arg_action);
                         if (r >= 0)
                                 return r;
+                        if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+                                /* requested operation is not supported or already in progress */
+                                return r;
+                        /* on all other errors, try low-level operation */
                 }
-
-                log_error("Must be root.");
-                return -EPERM;
         }
 
         if (arg_when > 0) {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_close_unref_ sd_bus *b = NULL;
+                _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
                 _cleanup_free_ char *m = NULL;
+                const char *action;
+
+                assert(geteuid() == 0);
 
                 if (avoid_bus()) {
                         log_error("Unable to perform operation without bus connection.");
@@ -7356,34 +7440,42 @@ static int halt_main(sd_bus *bus) {
                 if (!m)
                         return log_oom();
 
-                r = sd_bus_set_property(
-                                b,
-                                "org.freedesktop.login1",
-                                "/org/freedesktop/login1",
-                                "org.freedesktop.login1.Manager",
-                                "WallMessage",
-                                &error,
-                                "s", m);
+                r = sd_bus_call_method(
+                               b,
+                               "org.freedesktop.login1",
+                               "/org/freedesktop/login1",
+                               "org.freedesktop.login1.Manager",
+                               "SetWallMessage",
+                               &error,
+                               NULL,
+                               "sb",
+                               m,
+                               !arg_no_wall);
+
                 if (r < 0) {
-                        log_warning_errno(r, "Failed to set WallMessage property in logind: %s",
+                        log_warning_errno(r, "Failed to set wall message, ignoring: %s",
                                           bus_error_message(&error, r));
                         sd_bus_error_free(&error);
                 }
 
-                r = sd_bus_set_property(
-                                b,
-                                "org.freedesktop.login1",
-                                "/org/freedesktop/login1",
-                                "org.freedesktop.login1.Manager",
-                                "EnableWallMessages",
-                                &error,
-                                "b", !arg_no_wall);
-                if (r < 0) {
-                        log_warning_errno(r, "Failed to set EnableWallMessages property in logind: %s",
-                                          bus_error_message(&error, r));
-                        sd_bus_error_free(&error);
+                switch (arg_action) {
+                case ACTION_HALT:
+                        action = "halt";
+                        break;
+                case ACTION_POWEROFF:
+                        action = "poweroff";
+                        break;
+                case ACTION_KEXEC:
+                        action = "kexec";
+                        break;
+                default:
+                        action = "reboot";
+                        break;
                 }
 
+                if (arg_dry)
+                        action = strjoina("dry-", action);
+
                 r = sd_bus_call_method(
                                 b,
                                 "org.freedesktop.login1",
@@ -7393,10 +7485,7 @@ static int halt_main(sd_bus *bus) {
                                 &error,
                                 NULL,
                                 "st",
-                                arg_action == ACTION_HALT     ? "halt" :
-                                arg_action == ACTION_POWEROFF ? "poweroff" :
-                                arg_action == ACTION_KEXEC    ? "kexec" :
-                                                                "reboot",
+                                action,
                                 arg_when);
                 if (r < 0)
                         log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s",
@@ -7413,6 +7502,8 @@ static int halt_main(sd_bus *bus) {
         if (!arg_dry && !arg_force)
                 return start_with_fallback(bus);
 
+        assert(geteuid() == 0);
+
         if (!arg_no_wtmp) {
                 if (sd_booted() > 0)
                         log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
@@ -7449,7 +7540,7 @@ static int runlevel_main(void) {
 }
 
 int main(int argc, char*argv[]) {
-        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
@@ -7517,7 +7608,7 @@ int main(int argc, char*argv[]) {
 
         case ACTION_CANCEL_SHUTDOWN: {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_close_unref_ sd_bus *b = NULL;
+                _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
                 _cleanup_free_ char *m = NULL;
 
                 if (avoid_bus()) {
@@ -7537,30 +7628,20 @@ int main(int argc, char*argv[]) {
                         }
                 }
 
-                r = sd_bus_set_property(
-                                b,
-                                "org.freedesktop.login1",
-                                "/org/freedesktop/login1",
-                                "org.freedesktop.login1.Manager",
-                                "WallMessage",
-                                &error,
-                                "s", arg_wall);
-                if (r < 0) {
-                        log_warning_errno(r, "Failed to set WallMessage property in logind: %s",
-                                          bus_error_message(&error, r));
-                        sd_bus_error_free(&error);
-                }
+                r = sd_bus_call_method(
+                               b,
+                               "org.freedesktop.login1",
+                               "/org/freedesktop/login1",
+                               "org.freedesktop.login1.Manager",
+                               "SetWallMessage",
+                               &error,
+                               NULL,
+                               "sb",
+                               m,
+                               !arg_no_wall);
 
-                r = sd_bus_set_property(
-                                b,
-                                "org.freedesktop.login1",
-                                "/org/freedesktop/login1",
-                                "org.freedesktop.login1.Manager",
-                                "EnableWallMessages",
-                                &error,
-                                "b", !arg_no_wall);
                 if (r < 0) {
-                        log_warning_errno(r, "Failed to set EnableWallMessages property in logind: %s",
+                        log_warning_errno(r, "Failed to set wall message, ignoring: %s",
                                           bus_error_message(&error, r));
                         sd_bus_error_free(&error);
                 }