chiark / gitweb /
Prep v225: Applying various fixes and changes to src/login that got lost during git...
[elogind.git] / src / login / logind-dbus.c
index 0fcf2cc96000da38bd5342eef4fe46daee6ee9fe..768aa1a3190607f14a67465316c834453b04d6a2 100644 (file)
@@ -43,6 +43,7 @@
 #include "formats-util.h"
 #include "process-util.h"
 #include "terminal-util.h"
+#include "utmp-wtmp.h"
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
@@ -242,14 +243,13 @@ static int property_get_scheduled_shutdown(
 
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
 
-static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
         const char *name;
         Session *session;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -268,14 +268,13 @@ static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userda
         return sd_bus_reply_method_return(message, "o", p);
 }
 
-static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Session *session = NULL;
         Manager *m = userdata;
         pid_t pid;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -305,14 +304,13 @@ static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void
         return sd_bus_reply_method_return(message, "o", p);
 }
 
-static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
         uint32_t uid;
         User *user;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -331,14 +329,13 @@ static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata,
         return sd_bus_reply_method_return(message, "o", p);
 }
 
-static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
         User *user = NULL;
         pid_t pid;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -367,14 +364,13 @@ static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *us
         return sd_bus_reply_method_return(message, "o", p);
 }
 
-static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
         const char *name;
         Seat *seat;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -393,14 +389,13 @@ static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata,
         return sd_bus_reply_method_return(message, "o", p);
 }
 
-static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Session *session;
         Iterator i;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -433,17 +428,16 @@ static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *user
         if (r < 0)
                 return r;
 
-        return sd_bus_send(bus, reply, NULL);
+        return sd_bus_send(NULL, reply, NULL);
 }
 
-static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         Manager *m = userdata;
         User *user;
         Iterator i;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -474,17 +468,16 @@ static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdat
         if (r < 0)
                 return r;
 
-        return sd_bus_send(bus, reply, NULL);
+        return sd_bus_send(NULL, reply, NULL);
 }
 
-static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Seat *seat;
         Iterator i;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -512,16 +505,19 @@ static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdat
         if (r < 0)
                 return r;
 
-        return sd_bus_send(bus, reply, NULL);
+        return sd_bus_send(NULL, reply, NULL);
 }
 
-static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Inhibitor *inhibitor;
         Iterator i;
         int r;
 
+        assert(message);
+        assert(m);
+
         r = sd_bus_message_new_method_return(message, &reply);
         if (r < 0)
                 return r;
@@ -547,10 +543,10 @@ static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *us
         if (r < 0)
                 return r;
 
-        return sd_bus_send(bus, reply, NULL);
+        return sd_bus_send(NULL, reply, NULL);
 }
 
-static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
         uint32_t uid, leader, audit_id = 0;
         _cleanup_free_ char *id = NULL;
@@ -564,7 +560,6 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
         SessionClass c;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -731,15 +726,13 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
                         log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
                         audit_id = 0;
 
-                        free(id);
-                        id = NULL;
+                        id = mfree(id);
                 }
         }
 
         if (!id) {
                 do {
-                        free(id);
-                        id = NULL;
+                        id = mfree(id);
 
                         if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
                                 return -ENOMEM;
@@ -840,13 +833,12 @@ fail:
         return r;
 }
 
-static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         Session *session;
         const char *name;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -865,13 +857,12 @@ static int method_release_session(sd_bus *bus, sd_bus_message *message, void *us
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         Session *session;
         const char *name;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -883,17 +874,16 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u
         if (r < 0)
                 return r;
 
-        return bus_session_method_activate(bus, message, session, error);
+        return bus_session_method_activate(message, session, error);
 }
 
-static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         const char *session_name, *seat_name;
         Manager *m = userdata;
         Session *session;
         Seat *seat;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -922,13 +912,12 @@ static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message,
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         Session *session;
         const char *name;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -940,14 +929,13 @@ static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userd
         if (r < 0)
                 return r;
 
-        return bus_session_method_lock(bus, message, session, error);
+        return bus_session_method_lock(message, session, error);
 }
 
-static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -971,13 +959,12 @@ static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *user
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         const char *name;
         Manager *m = userdata;
         Session *session;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -989,16 +976,15 @@ static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userd
         if (r < 0)
                 return r;
 
-        return bus_session_method_kill(bus, message, session, error);
+        return bus_session_method_kill(message, session, error);
 }
 
-static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         uint32_t uid;
         User *user;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -1010,16 +996,15 @@ static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata
         if (r < 0)
                 return r;
 
-        return bus_user_method_kill(bus, message, user, error);
+        return bus_user_method_kill(message, user, error);
 }
 
-static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         const char *name;
         Session *session;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -1031,16 +1016,15 @@ static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *
         if (r < 0)
                 return r;
 
-        return bus_session_method_terminate(bus, message, session, error);
+        return bus_session_method_terminate(message, session, error);
 }
 
-static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         uint32_t uid;
         User *user;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -1052,16 +1036,15 @@ static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *use
         if (r < 0)
                 return r;
 
-        return bus_user_method_terminate(bus, message, user, error);
+        return bus_user_method_terminate(message, user, error);
 }
 
-static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         const char *name;
         Seat *seat;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -1073,10 +1056,10 @@ static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *use
         if (r < 0)
                 return r;
 
-        return bus_seat_method_terminate(bus, message, seat, error);
+        return bus_seat_method_terminate(message, seat, error);
 }
 
-static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *cc = NULL;
         Manager *m = userdata;
         int b, r;
@@ -1085,7 +1068,6 @@ static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *us
         uint32_t uid;
         int interactive;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -1265,12 +1247,11 @@ static int flush_devices(Manager *m) {
         return trigger_device(m, NULL);
 }
 
-static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         const char *sysfs, *seat;
         Manager *m = userdata;
         int interactive, r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -1304,11 +1285,10 @@ static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *user
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         int interactive, r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -1360,7 +1340,8 @@ static int bus_manager_log_shutdown(
                 InhibitWhat w,
                 const char *unit_name) {
 
-        const char *p, *q;
+        const char *p;
+        const char *q;
 
         assert(m);
         assert(unit_name);
@@ -1385,6 +1366,9 @@ static int bus_manager_log_shutdown(
                 q = NULL;
         }
 
+        if (m->wall_message)
+                p = strjoina(p, " (", m->wall_message, ")", NULL);
+
         return log_struct(LOG_NOTICE,
                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
                           p,
@@ -1543,11 +1527,11 @@ static int delay_shutdown_or_sleep(
         if (m->inhibit_timeout_source) {
                 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
                 if (r < 0)
-                        return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
+                        return log_error_errno(r, "sd_event_source_set_time() failed: %m");
 
                 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
                 if (r < 0)
-                        return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
+                        return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
         } else {
                 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
                                       timeout_val, 0, manager_inhibit_timeout_handler, m);
@@ -1727,7 +1711,7 @@ static int method_do_shutdown_or_sleep(
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_do_shutdown_or_sleep(
@@ -1741,7 +1725,7 @@ static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata,
                         error);
 }
 
-static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_do_shutdown_or_sleep(
@@ -1755,7 +1739,7 @@ static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, s
                         error);
 }
 
-static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_do_shutdown_or_sleep(
@@ -1769,6 +1753,76 @@ static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata,
                         error);
 }
 
+static int nologin_timeout_handler(
+                        sd_event_source *s,
+                        uint64_t usec,
+                        void *userdata) {
+
+        Manager *m = userdata;
+        int r;
+
+        log_info("Creating /run/nologin, blocking further logins...");
+
+        r = write_string_file_atomic("/run/nologin", "System is going down.");
+        if (r < 0)
+                log_error_errno(r, "Failed to create /run/nologin: %m");
+        else
+                m->unlink_nologin = true;
+
+        return 0;
+}
+
+static int update_schedule_file(Manager *m) {
+
+        int r;
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *t = NULL, *temp_path = NULL;
+
+        assert(m);
+
+        r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
+
+        t = cescape(m->wall_message);
+        if (!t)
+                return log_oom();
+
+        r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
+        if (r < 0)
+                return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
+
+        (void) fchmod(fileno(f), 0644);
+
+        fprintf(f,
+                "USEC="USEC_FMT"\n"
+                "WARN_WALL=%i\n"
+                "MODE=%s\n",
+                m->scheduled_shutdown_timeout,
+                m->enable_wall_messages,
+                m->scheduled_shutdown_type);
+
+        if (!isempty(m->wall_message))
+                fprintf(f, "WALL_MESSAGE=%s\n", t);
+
+        r = fflush_and_check(f);
+        if (r < 0)
+                goto fail;
+
+        if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        return 0;
+
+fail:
+                (void) unlink(temp_path);
+                (void) unlink("/run/systemd/shutdown/scheduled");
+
+        return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
+}
+
 static int manager_scheduled_shutdown_handler(
                         sd_event_source *s,
                         uint64_t usec,
@@ -1793,13 +1847,14 @@ static int manager_scheduled_shutdown_handler(
 
         r = execute_shutdown_or_sleep(m, 0, target, &error);
         if (r < 0)
-                return log_error_errno(r, "Unable to execute transition to %s: %m\n", target);
+                return log_error_errno(r, "Unable to execute transition to %s: %m", target);
 
         return 0;
 }
 
-static int method_schedule_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         const char *action_multiple_sessions = NULL;
         const char *action_ignore_inhibit = NULL;
         const char *action = NULL;
@@ -1837,16 +1892,16 @@ static int method_schedule_shutdown(sd_bus *bus, sd_bus_message *message, void *
         if (m->scheduled_shutdown_timeout_source) {
                 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
                 if (r < 0)
-                        return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
+                        return log_error_errno(r, "sd_event_source_set_time() failed: %m");
 
                 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
                 if (r < 0)
-                        return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
+                        return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
         } else {
                 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
                                       CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
                 if (r < 0)
-                        return log_error_errno(r, "sd_event_add_time() failed: %m\n");
+                        return log_error_errno(r, "sd_event_add_time() failed: %m");
         }
 
         r = free_and_strdup(&m->scheduled_shutdown_type, type);
@@ -1855,12 +1910,52 @@ static int method_schedule_shutdown(sd_bus *bus, sd_bus_message *message, void *
                 return log_oom();
         }
 
+        if (m->nologin_timeout_source) {
+                r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_time() failed: %m");
+
+                r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
+        } else {
+                r = sd_event_add_time(m->event, &m->nologin_timeout_source,
+                                      CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_add_time() failed: %m");
+        }
+
         m->scheduled_shutdown_timeout = elapse;
 
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
+        if (r >= 0) {
+                const char *tty;
+
+                (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
+                (void) sd_bus_creds_get_tty(creds, &tty);
+
+                r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
+                if (r < 0) {
+                        m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
+                        return log_oom();
+                }
+        }
+
+        r = manager_setup_wall_message_timer(m);
+        if (r < 0)
+                return r;
+
+        if (!isempty(type)) {
+                r = update_schedule_file(m);
+                if (r < 0)
+                        return r;
+        } else
+                (void) unlink("/run/systemd/shutdown/scheduled");
+
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int method_cancel_scheduled_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         bool cancelled;
 
@@ -1870,14 +1965,32 @@ static int method_cancel_scheduled_shutdown(sd_bus *bus, sd_bus_message *message
         cancelled = m->scheduled_shutdown_type != NULL;
 
         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
+        m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
+        m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
         free(m->scheduled_shutdown_type);
         m->scheduled_shutdown_type = NULL;
         m->scheduled_shutdown_timeout = 0;
 
+        if (cancelled) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                const char *tty = NULL;
+                uid_t uid = 0;
+                int r;
+
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
+                if (r >= 0) {
+                        (void) sd_bus_creds_get_uid(creds, &uid);
+                        (void) sd_bus_creds_get_tty(creds, &tty);
+                }
+
+                utmp_wall("The system shutdown has been cancelled",
+                          lookup_uid(uid), tty, logind_wall_tty_filter, m);
+        }
+
         return sd_bus_reply_method_return(message, "b", cancelled);
 }
 
-static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_do_shutdown_or_sleep(
@@ -1891,7 +2004,7 @@ static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata
                         error);
 }
 
-static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_do_shutdown_or_sleep(
@@ -1997,7 +2110,7 @@ static int method_can_shutdown_or_sleep(
         return sd_bus_reply_method_return(message, "s", result);
 }
 
-static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_can_shutdown_or_sleep(
@@ -2010,7 +2123,7 @@ static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userd
                         error);
 }
 
-static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_can_shutdown_or_sleep(
@@ -2023,7 +2136,7 @@ static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdat
                         error);
 }
 
-static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_can_shutdown_or_sleep(
@@ -2036,7 +2149,7 @@ static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userda
                         error);
 }
 
-static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_can_shutdown_or_sleep(
@@ -2049,7 +2162,7 @@ static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *user
                         error);
 }
 
-static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
         return method_can_shutdown_or_sleep(
@@ -2084,7 +2197,6 @@ static int property_get_reboot_to_firmware_setup(
 }
 
 static int method_set_reboot_to_firmware_setup(
-                sd_bus *bus,
                 sd_bus_message *message,
                 void *userdata,
                 sd_bus_error *error) {
@@ -2092,7 +2204,6 @@ static int method_set_reboot_to_firmware_setup(
         int b, r;
         Manager *m = userdata;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -2120,7 +2231,6 @@ static int method_set_reboot_to_firmware_setup(
 }
 
 static int method_can_reboot_to_firmware_setup(
-                sd_bus *bus,
                 sd_bus_message *message,
                 void *userdata,
                 sd_bus_error *error) {
@@ -2130,7 +2240,6 @@ static int method_can_reboot_to_firmware_setup(
         const char *result;
         Manager *m = userdata;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -2159,7 +2268,45 @@ static int method_can_reboot_to_firmware_setup(
         return sd_bus_reply_method_return(message, "s", result);
 }
 
-static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_set_wall_message(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error) {
+
+        int r;
+        Manager *m = userdata;
+        char *wall_message;
+        bool enable_wall_messages;
+
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
+        if (r < 0)
+                return r;
+
+        r = bus_verify_polkit_async(message,
+                                    CAP_SYS_ADMIN,
+                                    "org.freedesktop.login1.set-wall-message",
+                                    false,
+                                    UID_INVALID,
+                                    &m->polkit_registry,
+                                    error);
+
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return 1; /* Will call us back */
+
+        r = free_and_strdup(&m->wall_message, wall_message);
+        if (r < 0)
+                return log_oom();
+        m->enable_wall_messages = enable_wall_messages;
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         const char *who, *why, *what, *mode;
         _cleanup_free_ char *id = NULL;
@@ -2172,7 +2319,6 @@ static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata,
         uid_t uid;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -2231,8 +2377,7 @@ static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata,
                 return r;
 
         do {
-                free(id);
-                id = NULL;
+                id = mfree(id);
 
                 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
                         return -ENOMEM;
@@ -2275,6 +2420,9 @@ fail:
 const sd_bus_vtable manager_vtable[] = {
         SD_BUS_VTABLE_START(0),
 
+        SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
+        SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
+
         SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -2338,6 +2486,7 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
 
         SD_BUS_SIGNAL("SessionNew", "so", 0),
         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
@@ -2372,7 +2521,7 @@ static int session_jobs_reply(Session *s, const char *unit, const char *result)
         return r;
 }
 
-int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         const char *path, *result, *unit;
         Manager *m = userdata;
         Session *session;
@@ -2380,14 +2529,13 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
         User *user;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
         if (r < 0) {
                 bus_log_parse_error(r);
-                return r;
+                return 0;
         }
 
         if (m->action_job && streq(m->action_job, path)) {
@@ -2396,8 +2544,7 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
                 /* Tell people that they now may take a lock again */
                 send_prepare_for(m, m->action_what, false);
 
-                free(m->action_job);
-                m->action_job = NULL;
+                m->action_job = mfree(m->action_job);
                 m->action_unit = NULL;
                 m->action_what = 0;
                 return 0;
@@ -2406,10 +2553,8 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
         session = hashmap_get(m->session_units, unit);
         if (session) {
 
-                if (streq_ptr(path, session->scope_job)) {
-                        free(session->scope_job);
-                        session->scope_job = NULL;
-                }
+                if (streq_ptr(path, session->scope_job))
+                        session->scope_job = mfree(session->scope_job);
 
                 session_jobs_reply(session, unit, result);
 
@@ -2420,19 +2565,14 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
         user = hashmap_get(m->user_units, unit);
         if (user) {
 
-                if (streq_ptr(path, user->service_job)) {
-                        free(user->service_job);
-                        user->service_job = NULL;
-                }
+                if (streq_ptr(path, user->service_job))
+                        user->service_job = mfree(user->service_job);
 
-                if (streq_ptr(path, user->slice_job)) {
-                        free(user->slice_job);
-                        user->slice_job = NULL;
-                }
+                if (streq_ptr(path, user->slice_job))
+                        user->slice_job = mfree(user->slice_job);
 
-                LIST_FOREACH(sessions_by_user, session, user->sessions) {
+                LIST_FOREACH(sessions_by_user, session, user->sessions)
                         session_jobs_reply(session, unit, result);
-                }
 
                 user_save(user);
                 user_add_to_gc_queue(user);
@@ -2441,21 +2581,20 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
         return 0;
 }
 
-int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         const char *path, *unit;
         Manager *m = userdata;
         Session *session;
         User *user;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
         r = sd_bus_message_read(message, "so", &unit, &path);
         if (r < 0) {
                 bus_log_parse_error(r);
-                return r;
+                return 0;
         }
 
         session = hashmap_get(m->session_units, unit);
@@ -2469,7 +2608,7 @@ int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
         return 0;
 }
 
-int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *unit = NULL;
         Manager *m = userdata;
         const char *path;
@@ -2477,7 +2616,6 @@ int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdat
         User *user;
         int r;
 
-        assert(bus);
         assert(message);
         assert(m);
 
@@ -2488,8 +2626,10 @@ int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdat
         r = unit_name_from_dbus_path(path, &unit);
         if (r == -EINVAL) /* not a unit */
                 return 0;
-        if (r < 0)
-                return r;
+        if (r < 0) {
+                log_oom();
+                return 0;
+        }
 
         session = hashmap_get(m->session_units, unit);
         if (session)
@@ -2502,18 +2642,19 @@ int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdat
         return 0;
 }
 
-int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         Session *session;
         Iterator i;
         int b, r;
 
-        assert(bus);
+        assert(message);
+        assert(m);
 
         r = sd_bus_message_read(message, "b", &b);
         if (r < 0) {
                 bus_log_parse_error(r);
-                return r;
+                return 0;
         }
 
         if (b)
@@ -2528,40 +2669,6 @@ int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus
         return 0;
 }
 
-int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        const char *name, *old, *new;
-        Manager *m = userdata;
-        Session *session;
-        Iterator i;
-        int r;
-
-
-        char *key;
-
-        r = sd_bus_message_read(message, "sss", &name, &old, &new);
-        if (r < 0) {
-                bus_log_parse_error(r);
-                return r;
-        }
-
-        if (isempty(old) || !isempty(new))
-                return 0;
-
-        key = set_remove(m->busnames, (char*) old);
-        if (!key)
-                return 0;
-
-        /* Drop all controllers owned by this name */
-
-        free(key);
-
-        HASHMAP_FOREACH(session, m->sessions, i)
-                if (session_is_controller(session, old))
-                        session_drop_controller(session);
-
-        return 0;
-}
-
 int manager_send_changed(Manager *manager, const char *property, ...) {
         char **l;