chiark / gitweb /
systemctl: fix return value of systemctl start and friends
[elogind.git] / src / systemctl.c
index 2b34798d060b35fb3e4531bb9ffcabe32076dbc5..901804a766d1197f3d98543f3606818cc16d2827 100644 (file)
@@ -50,6 +50,8 @@
 #include "conf-parser.h"
 #include "sd-daemon.h"
 #include "shutdownd.h"
+#include "exit-status.h"
+#include "bus-errors.h"
 
 static const char *arg_type = NULL;
 static char **arg_property = NULL;
@@ -70,8 +72,6 @@ static bool arg_force = false;
 static bool arg_defaults = false;
 static char **arg_wall = NULL;
 static usec_t arg_when = 0;
-static bool arg_skip_fsck = false;
-static bool arg_force_fsck = false;
 static enum action {
         ACTION_INVALID,
         ACTION_SYSTEMCTL,
@@ -126,8 +126,7 @@ static const char *ansi_highlight_green(bool b) {
         return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
 }
 
-static bool error_is_no_service(DBusError *error) {
-
+static bool error_is_no_service(const DBusError *error) {
         assert(error);
 
         if (!dbus_error_is_set(error))
@@ -142,6 +141,34 @@ static bool error_is_no_service(DBusError *error) {
         return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
 }
 
+static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
+        assert(error);
+
+        if (!dbus_error_is_set(error))
+                return r;
+
+        if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
+            dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
+            dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
+            dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
+                return EXIT_NOPERMISSION;
+
+        if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
+                return EXIT_NOTINSTALLED;
+
+        if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
+            dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
+                return EXIT_NOTIMPLEMENTED;
+
+        if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
+                return EXIT_NOTCONFIGURED;
+
+        if (r != 0)
+                return r;
+
+        return EXIT_FAILURE;
+}
+
 static int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
 
         assert(iter);
@@ -216,11 +243,11 @@ static int compare_unit_info(const void *a, const void *b) {
         if (d1 && d2) {
                 int r;
 
-                if ((r = strcmp(d1, d2)) != 0)
+                if ((r = strcasecmp(d1, d2)) != 0)
                         return r;
         }
 
-        return strcmp(u->id, v->id);
+        return strcasecmp(u->id, v->id);
 }
 
 static int list_units(DBusConnection *bus, char **args, unsigned n) {
@@ -245,7 +272,7 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -309,8 +336,12 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
 
         qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
 
-        if (isatty(STDOUT_FILENO))
-                printf("%-45s %-6s %-12s %-12s %-15s %s\n", "UNIT", "LOAD", "ACTIVE", "SUB", "JOB", "DESCRIPTION");
+        if (isatty(STDOUT_FILENO)) {
+                if (columns() >= 80+12 || arg_full)
+                        printf("%-25s %-6s %-12s %-18s %-15s %s\n", "UNIT", "LOAD", "ACTIVE", "SUB", "JOB", "DESCRIPTION");
+                else
+                        printf("%-25s %-6s %-12s %-18s %-15s\n", "UNIT", "LOAD", "ACTIVE", "SUB", "JOB");
+        }
 
         for (k = 0; k < c; k++) {
                 const char *dot;
@@ -321,30 +352,47 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
                     (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0)) {
                         char *e;
                         int a = 0, b = 0;
-                        const char *on, *off;
+                        const char *on_loaded, *off_loaded;
+                        const char *on_active, *off_active;
+
+                        if (!streq(u->load_state, "loaded")) {
+                                on_loaded = ansi_highlight(true);
+                                off_loaded = ansi_highlight(false);
+                        } else
+                                on_loaded = off_loaded = "";
 
-                        if (streq(u->active_state, "maintenance")) {
-                                on = ansi_highlight(true);
-                                off = ansi_highlight(false);
+                        if (streq(u->active_state, "failed")) {
+                                on_active = ansi_highlight(true);
+                                off_active = ansi_highlight(false);
                         } else
-                                on = off = "";
+                                on_active = off_active = "";
+
+                        e = arg_full ? NULL : ellipsize(u->id, 25, 33);
+
+                        printf("%-25s %s%-6s%s %s%-12s %-18s%s%n",
+                               e ? e : u->id,
+                               on_loaded, u->load_state, off_loaded,
+                               on_active, u->active_state, u->sub_state, off_active,
+                               &a);
 
-                        e = arg_full ? NULL : ellipsize(u->id, 45, 33);
-                        printf("%-45s %-6s %s%-12s %-12s%s%n", e ? e : u->id, u->load_state, on, u->active_state, u->sub_state, off, &a);
                         free(e);
 
-                        a -= strlen(on) + strlen(off);
+                        a -= strlen(on_loaded) + strlen(off_loaded);
+                        a -= strlen(on_active) + strlen(off_active);
 
                         if (u->job_id != 0)
-                                printf(" => %-12s%n", u->job_type, &b);
+                                printf(" %-15s%n", u->job_type, &b);
                         else
                                 b = 1 + 15;
 
-                        if (a + b + 2 < columns()) {
+                        if (a + b + 1 < columns()) {
                                 if (u->job_id == 0)
                                         printf("                ");
 
-                                printf(" %.*s", columns() - a - b - 2, u->description);
+                                if (arg_full)
+                                        printf(" %s", u->description);
+                                else
+                                        printf(" %.*s", columns() - a - b - 1, u->description);
                         }
 
                         fputs("\n", stdout);
@@ -353,10 +401,10 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
 
         if (isatty(STDOUT_FILENO)) {
 
-                printf("\nLOAD   = Load State, reflects whether the unit configuration was properly loaded.\n"
-                       "ACTIVE = Active State, the high-level unit activation state, i.e. generalization of the substate.\n"
-                       "SUB    = Substate, the low-level unit activation state, possible values depend on unit type.\n"
-                       "JOB    = Job, shows pending jobs for the unit.\n");
+                printf("\nLOAD   = Reflects whether the unit definition was properly loaded.\n"
+                       "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
+                       "SUB    = The low-level unit activation state, values depend on unit type.\n"
+                       "JOB    = Pending job for the unit.\n");
 
                 if (arg_all)
                         printf("\n%u units listed.\n", c);
@@ -469,7 +517,7 @@ static int dot_one(DBusConnection *bus, const char *name, const char *path) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -552,7 +600,7 @@ static int dot(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -645,7 +693,7 @@ static int list_jobs(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -660,7 +708,8 @@ static int list_jobs(DBusConnection *bus, char **args, unsigned n) {
 
         dbus_message_iter_recurse(&iter, &sub);
 
-        printf("%4s %-45s %-17s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
+        if (isatty(STDOUT_FILENO))
+                printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
 
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
                 const char *name, *type, *state, *job_path, *unit_path;
@@ -686,8 +735,8 @@ static int list_jobs(DBusConnection *bus, char **args, unsigned n) {
                         goto finish;
                 }
 
-                e = arg_full ? NULL : ellipsize(name, 45, 33);
-                printf("%4u %-45s %-17s %-7s\n", id, e ? e : name, type, state);
+                e = arg_full ? NULL : ellipsize(name, 25, 33);
+                printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
                 free(e);
 
                 k++;
@@ -695,7 +744,9 @@ static int list_jobs(DBusConnection *bus, char **args, unsigned n) {
                 dbus_message_iter_next(&sub);
         }
 
-        printf("\n%u jobs listed.\n", k);
+        if (isatty(STDOUT_FILENO))
+                printf("\n%u jobs listed.\n", k);
+
         r = 0;
 
 finish:
@@ -742,7 +793,7 @@ static int load_unit(DBusConnection *bus, char **args, unsigned n) {
                 }
 
                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -810,7 +861,7 @@ static int cancel_job(DBusConnection *bus, char **args, unsigned n) {
                 }
 
                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -818,7 +869,7 @@ static int cancel_job(DBusConnection *bus, char **args, unsigned n) {
                 if (!dbus_message_get_args(reply, &error,
                                            DBUS_TYPE_OBJECT_PATH, &path,
                                            DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse reply: %s", error.message);
+                        log_error("Failed to parse reply: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -836,7 +887,7 @@ static int cancel_job(DBusConnection *bus, char **args, unsigned n) {
 
                 dbus_message_unref(reply);
                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -965,7 +1016,7 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
                                            DBUS_TYPE_OBJECT_PATH, &path,
                                            DBUS_TYPE_BOOLEAN, &success,
                                            DBUS_TYPE_INVALID))
-                        log_error("Failed to parse message: %s", error.message);
+                        log_error("Failed to parse message: %s", bus_error_message(&error));
                 else {
                         char *p;
 
@@ -999,7 +1050,7 @@ static int enable_wait_for_jobs(DBusConnection *bus) {
                            &error);
 
         if (dbus_error_is_set(&error)) {
-                log_error("Failed to add match: %s", error.message);
+                log_error("Failed to add match: %s", bus_error_message(&error));
                 dbus_error_free(&error);
                 return -EIO;
         }
@@ -1030,7 +1081,7 @@ static int wait_for_jobs(DBusConnection *bus, Set *s) {
                 ;
 
         if (!arg_quiet && d.failed)
-                log_error("Job failed, see logs for details.");
+                log_error("Job failed, see system logs for details.");
 
         r = d.failed ? -EIO : 0;
 
@@ -1045,10 +1096,10 @@ static int start_unit_one(
                 const char *method,
                 const char *name,
                 const char *mode,
+                DBusError *error,
                 Set *s) {
 
         DBusMessage *m = NULL, *reply = NULL;
-        DBusError error;
         const char *path;
         int r;
 
@@ -1056,10 +1107,9 @@ static int start_unit_one(
         assert(method);
         assert(name);
         assert(mode);
+        assert(error);
         assert(arg_no_block || s);
 
-        dbus_error_init(&error);
-
         if (!(m = dbus_message_new_method_call(
                               "org.freedesktop.systemd1",
                               "/org/freedesktop/systemd1",
@@ -1079,24 +1129,24 @@ static int start_unit_one(
                 goto finish;
         }
 
-        if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
+        if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
 
-                if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
+                if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
                         /* There's always a fallback possible for
                          * legacy actions. */
-                        r = 0;
+                        r = -EADDRNOTAVAIL;
                         goto finish;
                 }
 
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(error));
                 r = -EIO;
                 goto finish;
         }
 
-        if (!dbus_message_get_args(reply, &error,
+        if (!dbus_message_get_args(reply, error,
                                    DBUS_TYPE_OBJECT_PATH, &path,
                                    DBUS_TYPE_INVALID)) {
-                log_error("Failed to parse reply: %s", error.message);
+                log_error("Failed to parse reply: %s", bus_error_message(error));
                 r = -EIO;
                 goto finish;
         }
@@ -1121,7 +1171,7 @@ static int start_unit_one(
                 }
         }
 
-        r = 1;
+        r = 0;
 
 finish:
         if (m)
@@ -1130,8 +1180,6 @@ finish:
         if (reply)
                 dbus_message_unref(reply);
 
-        dbus_error_free(&error);
-
         return r;
 }
 
@@ -1167,10 +1215,13 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
                 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET
         };
 
-        int r;
+        int r, ret = 0;
         unsigned i;
         const char *method, *mode, *one_name;
         Set *s = NULL;
+        DBusError error;
+
+        dbus_error_init(&error);
 
         assert(bus);
 
@@ -1208,40 +1259,42 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!arg_no_block) {
-                if ((r = enable_wait_for_jobs(bus)) < 0) {
-                        log_error("Could not watch jobs: %s", strerror(-r));
+                if ((ret = enable_wait_for_jobs(bus)) < 0) {
+                        log_error("Could not watch jobs: %s", strerror(-ret));
                         goto finish;
                 }
 
                 if (!(s = set_new(string_hash_func, string_compare_func))) {
                         log_error("Failed to allocate set.");
-                        r = -ENOMEM;
+                        ret = -ENOMEM;
                         goto finish;
                 }
         }
 
-        r = 0;
-
         if (one_name) {
-                if ((r = start_unit_one(bus, method, one_name, mode, s)) <= 0)
+                if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
                         goto finish;
         } else {
                 for (i = 1; i < n; i++)
-                        if ((r = start_unit_one(bus, method, args[i], mode, s)) < 0)
-                                goto finish;
+                        if ((r = start_unit_one(bus, method, args[i], mode, &error, s)) != 0) {
+                                ret = translate_bus_error_to_exit_status(r, &error);
+                                dbus_error_free(&error);
+                        }
         }
 
         if (!arg_no_block)
-                if ((r = wait_for_jobs(bus, s)) < 0)
+                if ((r = wait_for_jobs(bus, s)) < 0) {
+                        ret = r;
                         goto finish;
-
-        r = 1;
+                }
 
 finish:
         if (s)
                 set_free_free(s);
 
-        return r;
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int start_special(DBusConnection *bus, char **args, unsigned n) {
@@ -1263,7 +1316,7 @@ static int check_unit(DBusConnection *bus, char **args, unsigned n) {
         const char
                 *interface = "org.freedesktop.systemd1.Unit",
                 *property = "ActiveState";
-        int r = -EADDRNOTAVAIL;
+        int r = 3; /* According to LSB: "program is not running" */
         DBusError error;
         unsigned i;
 
@@ -1308,7 +1361,7 @@ static int check_unit(DBusConnection *bus, char **args, unsigned n) {
                 if (!dbus_message_get_args(reply, &error,
                                            DBUS_TYPE_OBJECT_PATH, &path,
                                            DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse reply: %s", error.message);
+                        log_error("Failed to parse reply: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -1335,7 +1388,7 @@ static int check_unit(DBusConnection *bus, char **args, unsigned n) {
 
                 dbus_message_unref(reply);
                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -1360,7 +1413,7 @@ static int check_unit(DBusConnection *bus, char **args, unsigned n) {
                 if (!arg_quiet)
                         puts(state);
 
-                if (streq(state, "active") || startswith(state, "reloading"))
+                if (streq(state, "active") || streq(state, "reloading"))
                         r = 0;
 
                 dbus_message_unref(m);
@@ -1485,13 +1538,19 @@ typedef struct UnitStatusInfo {
         const char *path;
         const char *default_control_group;
 
+        usec_t inactive_exit_timestamp;
+        usec_t active_enter_timestamp;
+        usec_t active_exit_timestamp;
+        usec_t inactive_enter_timestamp;
+
         bool need_daemon_reload;
 
         /* Service */
         pid_t main_pid;
         pid_t control_pid;
         const char *status_text;
-        bool running;
+        bool running:1;
+        bool is_sysv:1;
 
         usec_t start_timestamp;
         usec_t exit_timestamp;
@@ -1518,6 +1577,9 @@ typedef struct UnitStatusInfo {
 static void print_status_info(UnitStatusInfo *i) {
         ExecStatusInfo *p;
         const char *on, *off, *ss;
+        usec_t timestamp;
+        char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
+        char since2[FORMAT_TIMESTAMP_MAX], *s2;
 
         assert(i);
 
@@ -1544,7 +1606,7 @@ static void print_status_info(UnitStatusInfo *i) {
 
         ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
 
-        if (streq_ptr(i->active_state, "maintenance")) {
+        if (streq_ptr(i->active_state, "failed")) {
                 on = ansi_highlight(true);
                 off = ansi_highlight(false);
         } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
@@ -1554,17 +1616,34 @@ static void print_status_info(UnitStatusInfo *i) {
                 on = off = "";
 
         if (ss)
-                printf("\t  Active: %s%s (%s)%s\n",
+                printf("\t  Active: %s%s (%s)%s",
                        on,
                        strna(i->active_state),
                        ss,
                        off);
         else
-                printf("\t  Active: %s%s%s\n",
+                printf("\t  Active: %s%s%s",
                        on,
                        strna(i->active_state),
                        off);
 
+        timestamp = (streq_ptr(i->active_state, "active")      ||
+                     streq_ptr(i->active_state, "reloading"))   ? i->active_enter_timestamp :
+                    (streq_ptr(i->active_state, "inactive")    ||
+                     streq_ptr(i->active_state, "failed"))      ? i->inactive_enter_timestamp :
+                    streq_ptr(i->active_state, "activating")    ? i->inactive_exit_timestamp :
+                                                                  i->active_exit_timestamp;
+
+        s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
+        s2 = format_timestamp(since2, sizeof(since2), timestamp);
+
+        if (s1)
+                printf(" since [%s; %s]\n", s2, s1);
+        else if (s2)
+                printf(" since [%s]\n", s2);
+        else
+                printf("\n");
+
         if (i->sysfs_path)
                 printf("\t  Device: %s\n", i->sysfs_path);
         else if (i->where)
@@ -1583,12 +1662,18 @@ static void print_status_info(UnitStatusInfo *i) {
                         continue;
 
                 t = strv_join(p->argv, " ");
-                printf("\t  Exited: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
+                printf("\t Process: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
                 free(t);
 
-                if (p->code == CLD_EXITED)
+                if (p->code == CLD_EXITED) {
+                        const char *c;
+
                         printf("status=%i", p->status);
-                else
+
+                        if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
+                                printf("/%s", c);
+
+                } else
                         printf("signal=%s", signal_to_string(p->status));
                 printf(")\n");
 
@@ -1606,7 +1691,7 @@ static void print_status_info(UnitStatusInfo *i) {
                 printf("\t");
 
                 if (i->main_pid > 0) {
-                        printf("    Main: %u", (unsigned) i->main_pid);
+                        printf("Main PID: %u", (unsigned) i->main_pid);
 
                         if (i->running) {
                                 char *t = NULL;
@@ -1618,9 +1703,15 @@ static void print_status_info(UnitStatusInfo *i) {
                         } else if (i->exit_code > 0) {
                                 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
 
-                                if (i->exit_code == CLD_EXITED)
+                                if (i->exit_code == CLD_EXITED) {
+                                        const char *c;
+
                                         printf("status=%i", i->exit_status);
-                                else
+
+                                        if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
+                                                printf("/%s", c);
+
+                                } else
                                         printf("signal=%s", signal_to_string(i->exit_status));
                                 printf(")");
                         }
@@ -1689,9 +1780,10 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                                 i->description = s;
                         else if (streq(name, "FragmentPath"))
                                 i->path = s;
-                        else if (streq(name, "SysVPath"))
+                        else if (streq(name, "SysVPath")) {
+                                i->is_sysv = true;
                                 i->path = s;
-                        else if (streq(name, "DefaultControlGroup"))
+                        else if (streq(name, "DefaultControlGroup"))
                                 i->default_control_group = s;
                         else if (streq(name, "StatusText"))
                                 i->status_text = s;
@@ -1764,6 +1856,14 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                         i->start_timestamp = (usec_t) u;
                 else if (streq(name, "ExecMainExitTimestamp"))
                         i->exit_timestamp = (usec_t) u;
+                else if (streq(name, "ActiveEnterTimestamp"))
+                        i->active_enter_timestamp = (usec_t) u;
+                else if (streq(name, "InactiveEnterTimestamp"))
+                        i->inactive_enter_timestamp = (usec_t) u;
+                else if (streq(name, "InactiveExitTimestamp"))
+                        i->inactive_exit_timestamp = (usec_t) u;
+                else if (streq(name, "ActiveExitTimestamp"))
+                        i->active_exit_timestamp = (usec_t) u;
 
                 break;
         }
@@ -2078,7 +2178,7 @@ static int show_one(DBusConnection *bus, const char *path, bool show_properties,
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2137,16 +2237,21 @@ static int show_one(DBusConnection *bus, const char *path, bool show_properties,
                 dbus_message_iter_next(&sub);
         }
 
+        r = 0;
+
         if (!show_properties)
                 print_status_info(&info);
 
+        if (!streq_ptr(info.active_state, "active") &&
+            !streq_ptr(info.active_state, "reloading"))
+                /* According to LSB: "program not running" */
+                r = 3;
+
         while ((p = info.exec)) {
                 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
                 exec_status_info_free(p);
         }
 
-        r = 0;
-
 finish:
         if (m)
                 dbus_message_unref(m);
@@ -2161,7 +2266,7 @@ finish:
 
 static int show(DBusConnection *bus, char **args, unsigned n) {
         DBusMessage *m = NULL, *reply = NULL;
-        int r;
+        int r, ret = 0;
         DBusError error;
         unsigned i;
         bool show_properties, new_line = false;
@@ -2177,7 +2282,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                 /* If not argument is specified inspect the manager
                  * itself */
 
-                r = show_one(bus, "/org/freedesktop/systemd1", show_properties, &new_line);
+                ret = show_one(bus, "/org/freedesktop/systemd1", show_properties, &new_line);
                 goto finish;
         }
 
@@ -2195,7 +2300,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                               "org.freedesktop.systemd1.Manager",
                                               "LoadUnit"))) {
                                 log_error("Could not allocate message.");
-                                r = -ENOMEM;
+                                ret = -ENOMEM;
                                 goto finish;
                         }
 
@@ -2203,15 +2308,15 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                                       DBUS_TYPE_STRING, &args[i],
                                                       DBUS_TYPE_INVALID)) {
                                 log_error("Could not append arguments to message.");
-                                r = -ENOMEM;
+                                ret = -ENOMEM;
                                 goto finish;
                         }
 
                         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
 
                                 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
-                                        log_error("Failed to issue method call: %s", error.message);
-                                        r = -EIO;
+                                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                                        ret = -EIO;
                                         goto finish;
                                 }
 
@@ -2224,7 +2329,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                                       "org.freedesktop.systemd1.Manager",
                                                       "GetUnit"))) {
                                         log_error("Could not allocate message.");
-                                        r = -ENOMEM;
+                                        ret = -ENOMEM;
                                         goto finish;
                                 }
 
@@ -2232,13 +2337,17 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                                               DBUS_TYPE_STRING, &args[i],
                                                               DBUS_TYPE_INVALID)) {
                                         log_error("Could not append arguments to message.");
-                                        r = -ENOMEM;
+                                        ret = -ENOMEM;
                                         goto finish;
                                 }
 
                                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                                        log_error("Failed to issue method call: %s", error.message);
-                                        r = -EIO;
+                                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+
+                                        if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
+                                                ret = 4; /* According to LSB: "program or service status is unknown" */
+                                        else
+                                                ret = -EIO;
                                         goto finish;
                                 }
                         }
@@ -2253,7 +2362,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                               "org.freedesktop.systemd1.Manager",
                                               "GetJob"))) {
                                 log_error("Could not allocate message.");
-                                r = -ENOMEM;
+                                ret = -ENOMEM;
                                 goto finish;
                         }
 
@@ -2261,13 +2370,13 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                                       DBUS_TYPE_UINT32, &id,
                                                       DBUS_TYPE_INVALID)) {
                                 log_error("Could not append arguments to message.");
-                                r = -ENOMEM;
+                                ret = -ENOMEM;
                                 goto finish;
                         }
 
                         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                                log_error("Failed to issue method call: %s", error.message);
-                                r = -EIO;
+                                log_error("Failed to issue method call: %s", bus_error_message(&error));
+                                ret = -EIO;
                                 goto finish;
                         }
                 } else {
@@ -2280,7 +2389,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                               "org.freedesktop.systemd1.Manager",
                                               "GetUnitByPID"))) {
                                 log_error("Could not allocate message.");
-                                r = -ENOMEM;
+                                ret = -ENOMEM;
                                 goto finish;
                         }
 
@@ -2288,13 +2397,13 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                                       DBUS_TYPE_UINT32, &id,
                                                       DBUS_TYPE_INVALID)) {
                                 log_error("Could not append arguments to message.");
-                                r = -ENOMEM;
+                                ret = -ENOMEM;
                                 goto finish;
                         }
 
                         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                                log_error("Failed to issue method call: %s", error.message);
-                                r = -EIO;
+                                log_error("Failed to issue method call: %s", bus_error_message(&error));
+                                ret = -EIO;
                                 goto finish;
                         }
                 }
@@ -2302,21 +2411,19 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                 if (!dbus_message_get_args(reply, &error,
                                            DBUS_TYPE_OBJECT_PATH, &path,
                                            DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse reply: %s", error.message);
-                        r = -EIO;
+                        log_error("Failed to parse reply: %s", bus_error_message(&error));
+                        ret = -EIO;
                         goto finish;
                 }
 
-                if ((r = show_one(bus, path, show_properties, &new_line)) < 0)
-                        goto finish;
+                if ((r = show_one(bus, path, show_properties, &new_line)) != 0)
+                        ret = r;
 
                 dbus_message_unref(m);
                 dbus_message_unref(reply);
                 m = reply = NULL;
         }
 
-        r = 0;
-
 finish:
         if (m)
                 dbus_message_unref(m);
@@ -2326,7 +2433,7 @@ finish:
 
         dbus_error_free(&error);
 
-        return r;
+        return ret;
 }
 
 static DBusHandlerResult monitor_filter(DBusConnection *connection, DBusMessage *message, void *data) {
@@ -2355,7 +2462,7 @@ static DBusHandlerResult monitor_filter(DBusConnection *connection, DBusMessage
                                            DBUS_TYPE_STRING, &id,
                                            DBUS_TYPE_OBJECT_PATH, &path,
                                            DBUS_TYPE_INVALID))
-                        log_error("Failed to parse message: %s", error.message);
+                        log_error("Failed to parse message: %s", bus_error_message(&error));
                 else if (streq(dbus_message_get_member(message), "UnitNew"))
                         printf("Unit %s added.\n", id);
                 else
@@ -2370,21 +2477,30 @@ static DBusHandlerResult monitor_filter(DBusConnection *connection, DBusMessage
                                            DBUS_TYPE_UINT32, &id,
                                            DBUS_TYPE_OBJECT_PATH, &path,
                                            DBUS_TYPE_INVALID))
-                        log_error("Failed to parse message: %s", error.message);
+                        log_error("Failed to parse message: %s", bus_error_message(&error));
                 else if (streq(dbus_message_get_member(message), "JobNew"))
                         printf("Job %u added.\n", id);
                 else
                         printf("Job %u removed.\n", id);
 
 
-        } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Unit", "Changed") ||
-                   dbus_message_is_signal(message, "org.freedesktop.systemd1.Job", "Changed")) {
+        } else if (dbus_message_is_signal(message, "org.freedesktop.DBus.Properties", "PropertiesChanged")) {
 
                 const char *path, *interface, *property = "Id";
                 DBusMessageIter iter, sub;
 
                 path = dbus_message_get_path(message);
-                interface = dbus_message_get_interface(message);
+
+                if (!dbus_message_get_args(message, &error,
+                                          DBUS_TYPE_STRING, &interface,
+                                          DBUS_TYPE_INVALID)) {
+                        log_error("Failed to parse message: %s", bus_error_message(&error));
+                        goto finish;
+                }
+
+                if (!streq(interface, "org.freedesktop.systemd1.Job") &&
+                    !streq(interface, "org.freedesktop.systemd1.Unit"))
+                        goto finish;
 
                 if (!(m = dbus_message_new_method_call(
                               "org.freedesktop.systemd1",
@@ -2404,7 +2520,7 @@ static DBusHandlerResult monitor_filter(DBusConnection *connection, DBusMessage
                 }
 
                 if (!(reply = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         goto finish;
                 }
 
@@ -2476,7 +2592,7 @@ static int monitor(DBusConnection *bus, char **args, unsigned n) {
                                    &error);
 
                 if (dbus_error_is_set(&error)) {
-                        log_error("Failed to add match: %s", error.message);
+                        log_error("Failed to add match: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -2484,25 +2600,12 @@ static int monitor(DBusConnection *bus, char **args, unsigned n) {
                 dbus_bus_add_match(bus,
                                    "type='signal',"
                                    "sender='org.freedesktop.systemd1',"
-                                   "interface='org.freedesktop.systemd1.Unit',"
-                                   "member='Changed'",
+                                   "interface='org.freedesktop.DBus.Properties',"
+                                   "member='PropertiesChanged'",
                                    &error);
 
                 if (dbus_error_is_set(&error)) {
-                        log_error("Failed to add match: %s", error.message);
-                        r = -EIO;
-                        goto finish;
-                }
-
-                dbus_bus_add_match(bus,
-                                   "type='signal',"
-                                   "sender='org.freedesktop.systemd1',"
-                                   "interface='org.freedesktop.systemd1.Job',"
-                                   "member='Changed'",
-                                   &error);
-
-                if (dbus_error_is_set(&error)) {
-                        log_error("Failed to add match: %s", error.message);
+                        log_error("Failed to add match: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -2525,7 +2628,7 @@ static int monitor(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2568,7 +2671,7 @@ static int dump(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2576,7 +2679,7 @@ static int dump(DBusConnection *bus, char **args, unsigned n) {
         if (!dbus_message_get_args(reply, &error,
                                    DBUS_TYPE_STRING, &text,
                                    DBUS_TYPE_INVALID)) {
-                log_error("Failed to parse reply: %s", error.message);
+                log_error("Failed to parse reply: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2632,7 +2735,7 @@ static int snapshot(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2640,7 +2743,7 @@ static int snapshot(DBusConnection *bus, char **args, unsigned n) {
         if (!dbus_message_get_args(reply, &error,
                                    DBUS_TYPE_OBJECT_PATH, &path,
                                    DBUS_TYPE_INVALID)) {
-                log_error("Failed to parse reply: %s", error.message);
+                log_error("Failed to parse reply: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2666,7 +2769,7 @@ static int snapshot(DBusConnection *bus, char **args, unsigned n) {
 
         dbus_message_unref(reply);
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2737,7 +2840,7 @@ static int delete_snapshot(DBusConnection *bus, char **args, unsigned n) {
                 }
 
                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -2745,7 +2848,7 @@ static int delete_snapshot(DBusConnection *bus, char **args, unsigned n) {
                 if (!dbus_message_get_args(reply, &error,
                                            DBUS_TYPE_OBJECT_PATH, &path,
                                            DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse reply: %s", error.message);
+                        log_error("Failed to parse reply: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -2763,7 +2866,7 @@ static int delete_snapshot(DBusConnection *bus, char **args, unsigned n) {
 
                 dbus_message_unref(reply);
                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -2806,7 +2909,7 @@ static int daemon_reload(DBusConnection *bus, char **args, unsigned n) {
                         streq(args[0], "clear-jobs")        ||
                         streq(args[0], "cancel")            ? "ClearJobs" :
                         streq(args[0], "daemon-reexec")     ? "Reexecute" :
-                        streq(args[0], "reset-maintenance") ? "ResetMaintenance" :
+                        streq(args[0], "reset-failed")      ? "ResetFailed" :
                         streq(args[0], "daemon-exit")       ? "Exit" :
                                                               "Reload";
         }
@@ -2829,7 +2932,7 @@ static int daemon_reload(DBusConnection *bus, char **args, unsigned n) {
                         goto finish;
                 }
 
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -2848,7 +2951,7 @@ finish:
         return r;
 }
 
-static int reset_maintenance(DBusConnection *bus, char **args, unsigned n) {
+static int reset_failed(DBusConnection *bus, char **args, unsigned n) {
         DBusMessage *m = NULL, *reply = NULL;
         unsigned i;
         int r;
@@ -2866,7 +2969,7 @@ static int reset_maintenance(DBusConnection *bus, char **args, unsigned n) {
                                       "org.freedesktop.systemd1",
                                       "/org/freedesktop/systemd1",
                                       "org.freedesktop.systemd1.Manager",
-                                      "ResetMaintenanceUnit"))) {
+                                      "ResetFailedUnit"))) {
                         log_error("Could not allocate message.");
                         r = -ENOMEM;
                         goto finish;
@@ -2881,7 +2984,7 @@ static int reset_maintenance(DBusConnection *bus, char **args, unsigned n) {
                 }
 
                 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                        log_error("Failed to issue method call: %s", error.message);
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
                         r = -EIO;
                         goto finish;
                 }
@@ -2935,7 +3038,7 @@ static int show_enviroment(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -3033,7 +3136,7 @@ static int set_environment(DBusConnection *bus, char **args, unsigned n) {
         }
 
         if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -3776,8 +3879,8 @@ static int systemctl_help(void) {
                "  status [NAME...|PID...]         Show runtime status of one or more units\n"
                "  show [NAME...|JOB...]           Show properties of one or more\n"
                "                                  units/jobs or the manager\n"
-               "  reset-maintenance [NAME...]     Reset maintenance state for all, one,\n"
-               "                                  or more units\n"
+               "  reset-failed [NAME...]          Reset failed state for all, one, or more\n"
+               "                                  units\n"
                "  enable [NAME...]                Enable one or more unit files\n"
                "  disable [NAME...]               Disable one or more unit files\n"
                "  is-enabled [NAME...]            Check whether unit files are enabled\n"
@@ -3829,7 +3932,7 @@ static int halt_help(void) {
 
 static int shutdown_help(void) {
 
-        printf("%s [OPTIONS...] [now] [WALL...]\n\n"
+        printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
                "Shut down the system.\n\n"
                "     --help      Show this help\n"
                "  -H --halt      Halt the machine\n"
@@ -3838,8 +3941,6 @@ static int shutdown_help(void) {
                "  -h             Equivalent to --poweroff, overriden by --halt\n"
                "  -k             Don't halt/power-off/reboot, just send warnings\n"
                "     --no-wall   Don't send wall message before halt/power-off/reboot\n"
-               "  -f             Skip fsck on reboot\n"
-               "  -F             Force fsck on reboot\n"
                "  -c             Cancel a pending shutdown\n",
                program_invocation_short_name);
 
@@ -3908,7 +4009,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "require",   no_argument,       NULL, ARG_REQUIRE   },
                 { "force",     no_argument,       NULL, ARG_FORCE     },
                 { "no-reload", no_argument,       NULL, ARG_NO_RELOAD },
-                { "defaults",   no_argument,      NULL, ARG_DEFAULTS  },
+                { "defaults",  no_argument,       NULL, ARG_DEFAULTS  },
                 { NULL,        0,                 NULL, 0             }
         };
 
@@ -4137,11 +4238,14 @@ static int parse_time_spec(const char *t, usec_t *_u) {
                         return -EINVAL;
 
                 n = now(CLOCK_REALTIME);
-                s = (time_t) n / USEC_PER_SEC;
+                s = (time_t) (n / USEC_PER_SEC);
+
+                zero(tm);
                 assert_se(localtime_r(&s, &tm));
 
                 tm.tm_hour = (int) hour;
                 tm.tm_min = (int) minute;
+                tm.tm_sec = 0;
 
                 assert_se(s = mktime(&tm));
 
@@ -4212,14 +4316,6 @@ static int shutdown_parse_argv(int argc, char *argv[]) {
                         /* Compatibility nops */
                         break;
 
-                case 'f':
-                        arg_skip_fsck = true;
-                        break;
-
-                case 'F':
-                        arg_force_fsck = true;
-                        break;
-
                 case 'c':
                         arg_action = ACTION_CANCEL_SHUTDOWN;
                         break;
@@ -4239,7 +4335,7 @@ static int shutdown_parse_argv(int argc, char *argv[]) {
                         return r;
                 }
         } else
-                arg_when = USEC_PER_MINUTE;
+                arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
 
         /* We skip the time argument */
         if (argc > optind + 1)
@@ -4469,7 +4565,7 @@ static int talk_upstart(void) {
                         goto finish;
                 }
 
-                log_error("Failed to connect to Upstart bus: %s", error.message);
+                log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -4513,7 +4609,7 @@ static int talk_upstart(void) {
                         goto finish;
                 }
 
-                log_error("Failed to issue method call: %s", error.message);
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;
         }
@@ -4620,7 +4716,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "default",               EQUAL, 1, start_special     },
                 { "rescue",                EQUAL, 1, start_special     },
                 { "emergency",             EQUAL, 1, start_special     },
-                { "reset-maintenance",     MORE,  1, reset_maintenance },
+                { "reset-failed",          MORE,  1, reset_failed      },
                 { "enable",                MORE,  2, enable_unit       },
                 { "disable",               MORE,  2, enable_unit       },
                 { "is-enabled",            MORE,  2, enable_unit       }
@@ -4696,21 +4792,20 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
         return verbs[i].dispatch(bus, argv + optind, left);
 }
 
-static int send_shutdownd(usec_t t, char mode) {
+static int send_shutdownd(usec_t t, char mode, bool warn, const char *message) {
         int fd = -1;
         struct msghdr msghdr;
         struct iovec iovec;
         union sockaddr_union sockaddr;
-        struct ucred *ucred;
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
-        } control;
         struct shutdownd_command c;
 
         zero(c);
         c.elapse = t;
         c.mode = mode;
+        c.warn_wall = warn;
+
+        if (message)
+                strncpy(c.wall_message, message, sizeof(c.wall_message));
 
         if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
                 return -errno;
@@ -4724,24 +4819,12 @@ static int send_shutdownd(usec_t t, char mode) {
         iovec.iov_base = (char*) &c;
         iovec.iov_len = sizeof(c);
 
-        zero(control);
-        control.cmsghdr.cmsg_level = SOL_SOCKET;
-        control.cmsghdr.cmsg_type = SCM_CREDENTIALS;
-        control.cmsghdr.cmsg_len = CMSG_LEN(sizeof(struct ucred));
-
-        ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
-        ucred->pid = getpid();
-        ucred->uid = getuid();
-        ucred->gid = getgid();
-
         zero(msghdr);
         msghdr.msg_name = &sockaddr;
         msghdr.msg_namelen = sizeof(sa_family_t) + 1 + sizeof("/org/freedesktop/systemd1/shutdownd") - 1;
 
         msghdr.msg_iov = &iovec;
         msghdr.msg_iovlen = 1;
-        msghdr.msg_control = &control;
-        msghdr.msg_controllen = control.cmsghdr.cmsg_len;
 
         if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
                 close_nointr_nofail(fd);
@@ -4775,7 +4858,7 @@ static int start_with_fallback(DBusConnection *bus) {
 
         if (bus) {
                 /* First, try systemd via D-Bus. */
-                if (start_unit(bus, NULL, 0) > 0)
+                if (start_unit(bus, NULL, 0) >= 0)
                         goto done;
         }
 
@@ -4801,26 +4884,30 @@ static int halt_main(DBusConnection *bus) {
         int r;
 
         if (geteuid() != 0) {
-                log_error("Must to be root.");
+                log_error("Must be root.");
                 return -EPERM;
         }
 
-        if (arg_force_fsck) {
-                if ((r = touch("/forcefsck")) < 0)
-                        log_warning("Failed to create /forcefsck: %s", strerror(-r));
-        } else if (arg_skip_fsck) {
-                if ((r = touch("/fastboot")) < 0)
-                        log_warning("Failed to create /fastboot: %s", strerror(-r));
-        }
-
         if (arg_when > 0) {
-                if ((r = send_shutdownd(arg_when,
-                                        arg_action == ACTION_HALT ? 'H' :
-                                        arg_action == ACTION_POWEROFF ? 'P' :
-                                        'r')) < 0)
+                char *m;
+                char date[FORMAT_TIMESTAMP_MAX];
+
+                m = strv_join(arg_wall, " ");
+                r = send_shutdownd(arg_when,
+                                   arg_action == ACTION_HALT     ? 'H' :
+                                   arg_action == ACTION_POWEROFF ? 'P' :
+                                                                   'r',
+                                   !arg_no_wall,
+                                   m);
+                free(m);
+
+                if (r < 0)
                         log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
-                else
+                else {
+                        log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
+                                 format_timestamp(date, sizeof(date), arg_when));
                         return 0;
+                }
         }
 
         if (!arg_dry && !arg_immediate)
@@ -4884,25 +4971,27 @@ static int runlevel_main(void) {
 }
 
 int main(int argc, char*argv[]) {
-        int r, retval = 1;
+        int r, retval = EXIT_FAILURE;
         DBusConnection *bus = NULL;
         DBusError error;
 
         dbus_error_init(&error);
 
         log_parse_environment();
+        log_open();
 
         if ((r = parse_argv(argc, argv)) < 0)
                 goto finish;
         else if (r == 0) {
-                retval = 0;
+                retval = EXIT_SUCCESS;
                 goto finish;
         }
 
         /* /sbin/runlevel doesn't need to communicate via D-Bus, so
          * let's shortcut this */
         if (arg_action == ACTION_RUNLEVEL) {
-                retval = runlevel_main() < 0;
+                r = runlevel_main();
+                retval = r < 0 ? EXIT_FAILURE : r;
                 goto finish;
         }
 
@@ -4910,15 +4999,14 @@ int main(int argc, char*argv[]) {
 
         switch (arg_action) {
 
-        case ACTION_SYSTEMCTL: {
-                retval = systemctl_main(bus, argc, argv, &error) < 0;
+        case ACTION_SYSTEMCTL:
+                r = systemctl_main(bus, argc, argv, &error);
                 break;
-        }
 
         case ACTION_HALT:
         case ACTION_POWEROFF:
         case ACTION_REBOOT:
-                retval = halt_main(bus) < 0;
+                r = halt_main(bus);
                 break;
 
         case ACTION_RUNLEVEL2:
@@ -4928,16 +5016,16 @@ int main(int argc, char*argv[]) {
         case ACTION_RESCUE:
         case ACTION_EMERGENCY:
         case ACTION_DEFAULT:
-                retval = start_with_fallback(bus) < 0;
+                r = start_with_fallback(bus);
                 break;
 
         case ACTION_RELOAD:
         case ACTION_REEXEC:
-                retval = reload_with_fallback(bus) < 0;
+                r = reload_with_fallback(bus);
                 break;
 
         case ACTION_CANCEL_SHUTDOWN:
-                retval = send_shutdownd(0, 0) < 0;
+                r = send_shutdownd(0, 0, false, NULL);
                 break;
 
         case ACTION_INVALID:
@@ -4946,6 +5034,8 @@ int main(int argc, char*argv[]) {
                 assert_not_reached("Unknown action");
         }
 
+        retval = r < 0 ? EXIT_FAILURE : r;
+
 finish:
 
         if (bus) {