[systemd-commits] 12 commits - Makefile.am TODO man/loginctl.xml man/machinectl.xml man/systemctl.xml src/core src/firstboot src/login src/machine src/nspawn src/shared src/systemctl src/test

Lennart Poettering lennart at kemper.freedesktop.org
Thu Jan 8 14:13:52 PST 2015


 Makefile.am                |    4 
 TODO                       |    8 
 man/loginctl.xml           |   68 +++++-
 man/machinectl.xml         |  350 ++++++++++++++++++++++++++++-----
 man/systemctl.xml          |  209 ++++++++++---------
 src/core/execute.c         |   12 -
 src/firstboot/firstboot.c  |    2 
 src/login/loginctl.c       |  475 ++++++++++++++++++++++++---------------------
 src/machine/machinectl.c   |  142 ++++++++++---
 src/nspawn/nspawn.c        |    2 
 src/shared/copy.c          |    9 
 src/shared/copy.h          |    4 
 src/shared/logs-show.c     |    8 
 src/shared/logs-show.h     |    5 
 src/shared/machine-image.c |    9 
 src/systemctl/systemctl.c  |   78 ++++---
 src/test/test-copy.c       |    2 
 17 files changed, 923 insertions(+), 464 deletions(-)

New commits:
commit a47e6701bfc45519a4e038daa52e9236e932f59a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 23:13:28 2015 +0100

    update TODO

diff --git a/TODO b/TODO
index ee682c0..90c321c 100644
--- a/TODO
+++ b/TODO
@@ -45,6 +45,14 @@ Release 219 preparations:
 
 Features:
 
+* nspawn should lock container images while running off them
+
+* when invoking "loginctl session-status" default to callers session
+
+* logind,machined: add generic catch-all polkit verbs for most priviliged operations, similar to systemd itself
+
+* "machinectl status" should also show logs of the container in question
+
 * nspawn: don't change superblock mount options from nspawn for cgroup hierarchies
 
 * "machinectl list-images" should show os-release data, as well as machine-info data (including deployment level)

commit d5243d628624038567c576e9b69c1d775eb05a05
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 23:12:16 2015 +0100

    core: make EPERM errors when applying OOM adjustment for forked processes non-fatal
    
    This should be useful for user namespaces.

diff --git a/src/core/execute.c b/src/core/execute.c
index 0af4227..63d295c 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1406,12 +1406,16 @@ static int exec_child(ExecCommand *command,
         }
 
         if (context->oom_score_adjust_set) {
-                char t[16];
+                char t[DECIMAL_STR_MAX(context->oom_score_adjust)];
 
-                snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
-                char_array_0(t);
+                /* When we can't make this change due to EPERM, then
+                 * let's silently skip over it. User namespaces
+                 * prohibit write access to this file, and we
+                 * shouldn't trip up over that. */
 
-                if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
+                sprintf(t, "%i", context->oom_score_adjust);
+                err = write_string_file("/proc/self/oom_score_adj", t);
+                if (err < 0 && err != -EPERM) {
                         *error = EXIT_OOM_ADJUST;
                         return -errno;
                 }

commit f7621db0e38c3e96d48766ae648f1b7a0949ea13
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 23:11:35 2015 +0100

    loginctl: port to generic verbs.h API

diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 9f77903..0fdd42b 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -41,6 +41,7 @@
 #include "cgroup-show.h"
 #include "cgroup-util.h"
 #include "spawn-polkit-agent.h"
+#include "verbs.h"
 
 static char **arg_property = NULL;
 static bool arg_all = false;
@@ -85,14 +86,18 @@ static OutputFlags get_output_flags(void) {
                 on_tty() * OUTPUT_COLOR;
 }
 
-static int list_sessions(sd_bus *bus, char **args, unsigned n) {
+static int list_sessions(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         const char *id, *user, *seat, *object;
+        sd_bus *bus = userdata;
         unsigned k = 0;
         uint32_t uid;
         int r;
 
+        assert(bus);
+        assert(argv);
+
         pager_open_if_enabled();
 
         r = sd_bus_call_method(
@@ -128,14 +133,18 @@ static int list_sessions(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int list_users(sd_bus *bus, char **args, unsigned n) {
+static int list_users(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         const char *user, *object;
+        sd_bus *bus = userdata;
         unsigned k = 0;
         uint32_t uid;
         int r;
 
+        assert(bus);
+        assert(argv);
+
         pager_open_if_enabled();
 
         r = sd_bus_call_method(
@@ -171,13 +180,17 @@ static int list_users(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int list_seats(sd_bus *bus, char **args, unsigned n) {
+static int list_seats(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         const char *seat, *object;
+        sd_bus *bus = userdata;
         unsigned k = 0;
         int r;
 
+        assert(bus);
+        assert(argv);
+
         pager_open_if_enabled();
 
         r = sd_bus_call_method(
@@ -659,25 +672,25 @@ static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
         return r;
 }
 
-static int show_session(sd_bus *bus, char **args, unsigned n) {
+static int show_session(int argc, char *argv[], void *userdata) {
         bool properties, new_line = false;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
         assert(bus);
-        assert(args);
+        assert(argv);
 
-        properties = !strstr(args[0], "status");
+        properties = !strstr(argv[0], "status");
 
         pager_open_if_enabled();
 
-        if (properties && n <= 1) {
+        if (properties && argc <= 1) {
                 /* If not argument is specified inspect the manager
                  * itself */
                 return show_properties(bus, "/org/freedesktop/login1", &new_line);
         }
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
                 const char *path = NULL;
@@ -689,7 +702,7 @@ static int show_session(sd_bus *bus, char **args, unsigned n) {
                                 "org.freedesktop.login1.Manager",
                                 "GetSession",
                                 &error, &reply,
-                                "s", args[i]);
+                                "s", argv[i]);
                 if (r < 0) {
                         log_error("Failed to get session: %s", bus_error_message(&error, r));
                         return r;
@@ -711,33 +724,33 @@ static int show_session(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int show_user(sd_bus *bus, char **args, unsigned n) {
+static int show_user(int argc, char *argv[], void *userdata) {
         bool properties, new_line = false;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
         assert(bus);
-        assert(args);
+        assert(argv);
 
-        properties = !strstr(args[0], "status");
+        properties = !strstr(argv[0], "status");
 
         pager_open_if_enabled();
 
-        if (properties && n <= 1) {
+        if (properties && argc <= 1) {
                 /* If not argument is specified inspect the manager
                  * itself */
                 return show_properties(bus, "/org/freedesktop/login1", &new_line);
         }
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
                 const char *path = NULL;
                 uid_t uid;
 
-                r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+                r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+                        return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
 
                 r = sd_bus_call_method(
                                 bus,
@@ -768,25 +781,25 @@ static int show_user(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int show_seat(sd_bus *bus, char **args, unsigned n) {
+static int show_seat(int argc, char *argv[], void *userdata) {
         bool properties, new_line = false;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
         assert(bus);
-        assert(args);
+        assert(argv);
 
-        properties = !strstr(args[0], "status");
+        properties = !strstr(argv[0], "status");
 
         pager_open_if_enabled();
 
-        if (properties && n <= 1) {
+        if (properties && argc <= 1) {
                 /* If not argument is specified inspect the manager
                  * itself */
                 return show_properties(bus, "/org/freedesktop/login1", &new_line);
         }
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
                 const char *path = NULL;
@@ -798,7 +811,7 @@ static int show_seat(sd_bus *bus, char **args, unsigned n) {
                                 "org.freedesktop.login1.Manager",
                                 "GetSeat",
                                 &error, &reply,
-                                "s", args[i]);
+                                "s", argv[i]);
                 if (r < 0) {
                         log_error("Failed to get seat: %s", bus_error_message(&error, r));
                         return r;
@@ -820,28 +833,29 @@ static int show_seat(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int activate(sd_bus *bus, char **args, unsigned n) {
+static int activate(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
 
                 r = sd_bus_call_method (
                                 bus,
                                 "org.freedesktop.login1",
                                 "/org/freedesktop/login1",
                                 "org.freedesktop.login1.Manager",
-                                streq(args[0], "lock-session")      ? "LockSession" :
-                                streq(args[0], "unlock-session")    ? "UnlockSession" :
-                                streq(args[0], "terminate-session") ? "TerminateSession" :
+                                streq(argv[0], "lock-session")      ? "LockSession" :
+                                streq(argv[0], "unlock-session")    ? "UnlockSession" :
+                                streq(argv[0], "terminate-session") ? "TerminateSession" :
                                                                       "ActivateSession",
                                 &error, NULL,
-                                "s", args[i]);
+                                "s", argv[i]);
                 if (r < 0) {
                         log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
                         return r;
@@ -851,19 +865,20 @@ static int activate(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int kill_session(sd_bus *bus, char **args, unsigned n) {
+static int kill_session(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
         if (!arg_kill_who)
                 arg_kill_who = "all";
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
 
                 r = sd_bus_call_method (
                         bus,
@@ -872,7 +887,7 @@ static int kill_session(sd_bus *bus, char **args, unsigned n) {
                         "org.freedesktop.login1.Manager",
                         "KillSession",
                         &error, NULL,
-                        "ssi", args[i], arg_kill_who, arg_signal);
+                        "ssi", argv[i], arg_kill_who, arg_signal);
                 if (r < 0) {
                         log_error("Could not kill session: %s", bus_error_message(&error, -r));
                         return r;
@@ -882,24 +897,25 @@ static int kill_session(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int enable_linger(sd_bus *bus, char **args, unsigned n) {
+static int enable_linger(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned i;
+        sd_bus *bus = userdata;
         bool b;
-        int r;
+        int r, i;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
-        b = streq(args[0], "enable-linger");
+        b = streq(argv[0], "enable-linger");
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
                 uid_t uid;
 
-                r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+                r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+                        return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
 
                 r = sd_bus_call_method (
                         bus,
@@ -918,21 +934,22 @@ static int enable_linger(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int terminate_user(sd_bus *bus, char **args, unsigned n) {
+static int terminate_user(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
                 uid_t uid;
 
-                r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+                r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+                        return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
 
                 r = sd_bus_call_method (
                         bus,
@@ -951,24 +968,25 @@ static int terminate_user(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int kill_user(sd_bus *bus, char **args, unsigned n) {
+static int kill_user(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
         if (!arg_kill_who)
                 arg_kill_who = "all";
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
                 uid_t uid;
 
-                r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+                r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+                        return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
 
                 r = sd_bus_call_method (
                         bus,
@@ -987,16 +1005,17 @@ static int kill_user(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int attach(sd_bus *bus, char **args, unsigned n) {
+static int attach(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
-        for (i = 2; i < n; i++) {
+        for (i = 2; i < argc; i++) {
 
                 r = sd_bus_call_method (
                         bus,
@@ -1005,7 +1024,7 @@ static int attach(sd_bus *bus, char **args, unsigned n) {
                         "org.freedesktop.login1.Manager",
                         "AttachDevice",
                         &error, NULL,
-                        "ssb", args[1], args[i], true);
+                        "ssb", argv[1], argv[i], true);
 
                 if (r < 0) {
                         log_error("Could not attach device: %s", bus_error_message(&error, -r));
@@ -1016,11 +1035,13 @@ static int attach(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static int flush_devices(sd_bus *bus, char **args, unsigned n) {
+static int flush_devices(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        sd_bus *bus = userdata;
         int r;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
@@ -1038,20 +1059,22 @@ static int flush_devices(sd_bus *bus, char **args, unsigned n) {
         return r;
 }
 
-static int lock_sessions(sd_bus *bus, char **args, unsigned n) {
+static int lock_sessions(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        sd_bus *bus = userdata;
         int r;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
-        r = sd_bus_call_method (
+        r = sd_bus_call_method(
                         bus,
                         "org.freedesktop.login1",
                         "/org/freedesktop/login1",
                         "org.freedesktop.login1.Manager",
-                        streq(args[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
+                        streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
                         &error, NULL,
                         NULL);
         if (r < 0)
@@ -1060,25 +1083,26 @@ static int lock_sessions(sd_bus *bus, char **args, unsigned n) {
         return r;
 }
 
-static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
+static int terminate_seat(int argc, char *argv[], void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned i;
-        int r;
+        sd_bus *bus = userdata;
+        int r, i;
 
-        assert(args);
+        assert(bus);
+        assert(argv);
 
         polkit_agent_open_if_enabled();
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < argc; i++) {
 
-                r = sd_bus_call_method (
+                r = sd_bus_call_method(
                         bus,
                         "org.freedesktop.login1",
                         "/org/freedesktop/login1",
                         "org.freedesktop.login1.Manager",
                         "TerminateSeat",
                         &error, NULL,
-                        "s", args[i]);
+                        "s", argv[i]);
                 if (r < 0) {
                         log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
                         return r;
@@ -1088,7 +1112,7 @@ static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
-static void help(void) {
+static int help(int argc, char *argv[], void *userdata) {
 
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
                "Send control commands to or query the login manager.\n\n"
@@ -1134,6 +1158,8 @@ static void help(void) {
                "  flush-devices            Flush all device associations\n"
                "  terminate-seat NAME...   Terminate all sessions on one or more seats\n"
                , program_invocation_short_name);
+
+        return 0;
 }
 
 static int parse_argv(int argc, char *argv[]) {
@@ -1174,7 +1200,7 @@ static int parse_argv(int argc, char *argv[]) {
                 switch (c) {
 
                 case 'h':
-                        help();
+                        help(0, NULL, NULL);
                         return 0;
 
                 case ARG_VERSION:
@@ -1261,101 +1287,37 @@ static int parse_argv(int argc, char *argv[]) {
         return 1;
 }
 
-static int loginctl_main(sd_bus *bus, int argc, char *argv[]) {
-
-        static const struct {
-                const char* verb;
-                const enum {
-                        MORE,
-                        LESS,
-                        EQUAL
-                } argc_cmp;
-                const int argc;
-                int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
-        } verbs[] = {
-                { "list-sessions",         LESS,   1, list_sessions     },
-                { "session-status",        MORE,   2, show_session      },
-                { "show-session",          MORE,   1, show_session      },
-                { "activate",              EQUAL,  2, activate          },
-                { "lock-session",          MORE,   2, activate          },
-                { "unlock-session",        MORE,   2, activate          },
-                { "lock-sessions",         EQUAL,  1, lock_sessions     },
-                { "unlock-sessions",       EQUAL,  1, lock_sessions     },
-                { "terminate-session",     MORE,   2, activate          },
-                { "kill-session",          MORE,   2, kill_session      },
-                { "list-users",            EQUAL,  1, list_users        },
-                { "user-status",           MORE,   2, show_user         },
-                { "show-user",             MORE,   1, show_user         },
-                { "enable-linger",         MORE,   2, enable_linger     },
-                { "disable-linger",        MORE,   2, enable_linger     },
-                { "terminate-user",        MORE,   2, terminate_user    },
-                { "kill-user",             MORE,   2, kill_user         },
-                { "list-seats",            EQUAL,  1, list_seats        },
-                { "seat-status",           MORE,   2, show_seat         },
-                { "show-seat",             MORE,   1, show_seat         },
-                { "attach",                MORE,   3, attach            },
-                { "flush-devices",         EQUAL,  1, flush_devices     },
-                { "terminate-seat",        MORE,   2, terminate_seat    },
+static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
+
+        static const Verb verbs[] = {
+                { "help",              VERB_ANY, VERB_ANY, 0,            help              },
+                { "list-sessions",     VERB_ANY, 1,        VERB_DEFAULT, list_sessions     },
+                { "session-status",    2,        VERB_ANY, 0,            show_session      },
+                { "show-session",      VERB_ANY, VERB_ANY, 0,            show_session      },
+                { "activate",          2,        2,        0,            activate          },
+                { "lock-session",      2,        VERB_ANY, 0,            activate          },
+                { "unlock-session",    2,        VERB_ANY, 0,            activate          },
+                { "lock-sessions",     VERB_ANY, 1,        0,            lock_sessions     },
+                { "unlock-sessions",   VERB_ANY, 1,        0,            lock_sessions     },
+                { "terminate-session", 2,        VERB_ANY, 0,            activate          },
+                { "kill-session",      2,        VERB_ANY, 0,            kill_session      },
+                { "list-users",        VERB_ANY, 1,        0,            list_users        },
+                { "user-status",       2,        VERB_ANY, 0,            show_user         },
+                { "show-user",         VERB_ANY, VERB_ANY, 0,            show_user         },
+                { "enable-linger",     2,        VERB_ANY, 0,            enable_linger     },
+                { "disable-linger",    2,        VERB_ANY, 0,            enable_linger     },
+                { "terminate-user",    2,        VERB_ANY, 0,            terminate_user    },
+                { "kill-user",         2,        VERB_ANY, 0,            kill_user         },
+                { "list-seats",        VERB_ANY, 1,        0,            list_seats        },
+                { "seat-status",       2,        VERB_ANY, 0,            show_seat         },
+                { "show-seat",         VERB_ANY, 1,        0,            show_seat         },
+                { "attach",            3,        VERB_ANY, 0,            attach            },
+                { "flush-devices",     VERB_ANY, 1,        0,            flush_devices     },
+                { "terminate-seat",    2,        VERB_ANY, 0,            terminate_seat    },
+                {}
         };
 
-        int left;
-        unsigned i;
-
-        assert(argc >= 0);
-        assert(argv);
-
-        left = argc - optind;
-
-        if (left <= 0)
-                /* Special rule: no arguments means "list-sessions" */
-                i = 0;
-        else {
-                if (streq(argv[optind], "help")) {
-                        help();
-                        return 0;
-                }
-
-                for (i = 0; i < ELEMENTSOF(verbs); i++)
-                        if (streq(argv[optind], verbs[i].verb))
-                                break;
-
-                if (i >= ELEMENTSOF(verbs)) {
-                        log_error("Unknown operation %s", argv[optind]);
-                        return -EINVAL;
-                }
-        }
-
-        switch (verbs[i].argc_cmp) {
-
-        case EQUAL:
-                if (left != verbs[i].argc) {
-                        log_error("Invalid number of arguments.");
-                        return -EINVAL;
-                }
-
-                break;
-
-        case MORE:
-                if (left < verbs[i].argc) {
-                        log_error("Too few arguments.");
-                        return -EINVAL;
-                }
-
-                break;
-
-        case LESS:
-                if (left > verbs[i].argc) {
-                        log_error("Too many arguments.");
-                        return -EINVAL;
-                }
-
-                break;
-
-        default:
-                assert_not_reached("Unknown comparison operator.");
-        }
-
-        return verbs[i].dispatch(bus, argv + optind, left);
+        return dispatch_verb(argc, argv, verbs, bus);
 }
 
 int main(int argc, char *argv[]) {
@@ -1376,10 +1338,11 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = loginctl_main(bus, argc, argv);
+        r = loginctl_main(argc, argv, bus);
 
 finish:
         pager_close();
+        polkit_agent_close();
 
         strv_free(arg_property);
 
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index dbfc245..749170e 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1778,8 +1778,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "  clone NAME NAME             Clone an image\n"
                "  rename NAME NAME            Rename an image\n"
                "  read-only NAME [BOOL]       Mark or unmark image read-only\n"
-               "  remove NAME...              Remove an image\n",
-               program_invocation_short_name);
+               "  remove NAME...              Remove an image\n"
+               , program_invocation_short_name);
 
         return 0;
 }

commit a03fe1a5d56be86fcc383090e191224590a1ab5d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 19:16:44 2015 +0100

    man: remove references to systemadm from systemctl man page
    
    The tool is badly maintained and we shouldn't refence such old cruft.

diff --git a/man/systemctl.xml b/man/systemctl.xml
index dd9fd99..caad131 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1718,9 +1718,9 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemadm</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.resource-management</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,

commit f2068bcce01db31cdc9422f44185f3b49c04d2ce
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 19:15:49 2015 +0100

    machined: when cloning a raw disk image, also set the NOCOW flag

diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index d087ef3..ce79574 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -256,7 +256,7 @@ static int process_locale(void) {
         if (arg_copy_locale && arg_root) {
 
                 mkdir_parents(etc_localeconf, 0755);
-                r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644);
+                r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644, 0);
                 if (r != -ENOENT) {
                         if (r < 0)
                                 return log_error_errno(r, "Failed to copy %s: %m", etc_localeconf);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index e5a24dd..59f6f38 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1092,7 +1092,7 @@ static int setup_resolv_conf(const char *dest) {
                 return 0;
         }
 
-        r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644);
+        r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644, 0);
         if (r < 0) {
                 log_warning_errno(r, "Failed to copy /etc/resolv.conf to %s: %m", where);
 
diff --git a/src/shared/copy.c b/src/shared/copy.c
index 3df6367..b681f6f 100644
--- a/src/shared/copy.c
+++ b/src/shared/copy.c
@@ -359,7 +359,7 @@ int copy_file_fd(const char *from, int fdt, bool try_reflink) {
         return r;
 }
 
-int copy_file(const char *from, const char *to, int flags, mode_t mode) {
+int copy_file(const char *from, const char *to, int flags, mode_t mode, int chattr_flags) {
         int fdt, r;
 
         assert(from);
@@ -371,6 +371,9 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode) {
                         return -errno;
         }
 
+        if (chattr_flags != 0)
+                (void) chattr_fd(fdt, true, chattr_flags);
+
         r = copy_file_fd(from, fdt, true);
         if (r < 0) {
                 close(fdt);
@@ -386,7 +389,7 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode) {
         return 0;
 }
 
-int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace) {
+int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, int chattr_flags) {
         _cleanup_free_ char *t;
         int r;
 
@@ -397,7 +400,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace
         if (r < 0)
                 return r;
 
-        r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode);
+        r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags);
         if (r < 0)
                 return r;
 
diff --git a/src/shared/copy.h b/src/shared/copy.h
index 58159a0..e4e3079 100644
--- a/src/shared/copy.h
+++ b/src/shared/copy.h
@@ -25,8 +25,8 @@
 #include <sys/types.h>
 
 int copy_file_fd(const char *from, int to, bool try_reflink);
-int copy_file(const char *from, const char *to, int flags, mode_t mode);
-int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace);
+int copy_file(const char *from, const char *to, int flags, mode_t mode, int chattr_flags);
+int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, int chattr_flags);
 int copy_tree(const char *from, const char *to, bool merge);
 int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge);
 int copy_directory_fd(int dirfd, const char *to, bool merge);
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index 36b64e1..25689ca 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -20,6 +20,7 @@
 ***/
 
 #include <sys/statfs.h>
+#include <linux/fs.h>
 #include <fcntl.h>
 
 #include "strv.h"
@@ -440,7 +441,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
         case IMAGE_GPT:
                 new_path = strappenda("/var/lib/container/", new_name, ".gpt");
 
-                r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644, false);
+                r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644, false, FS_NOCOW_FL);
                 break;
 
         default:
@@ -477,6 +478,12 @@ int image_read_only(Image *i, bool b) {
 
                 if (chmod(i->path, (st.st_mode & 0444) | (b ? 0000 : 0200)) < 0)
                         return -errno;
+
+                /* If the images is now read-only, it's a good time to
+                 * defrag it, given that no write patterns will
+                 * fragment it again. */
+                if (b)
+                        (void) btrfs_defrag(i->path);
                 break;
         }
 
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 74528dd..3121428 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5669,7 +5669,7 @@ static int create_edit_temp_file(const char *new_path, const char *original_path
                 return r;
         }
 
-        r = copy_file(original_path, t, 0, 0644);
+        r = copy_file(original_path, t, 0, 0644, 0);
         if (r == -ENOENT) {
                 r = touch(t);
                 if (r < 0) {
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index d70a0be..3e1607e 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -44,7 +44,7 @@ static void test_copy_file(void) {
 
         assert_se(write_string_file(fn, "foo bar bar bar foo") == 0);
 
-        assert_se(copy_file(fn, fn_copy, 0, 0644) == 0);
+        assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0);
 
         assert_se(read_full_file(fn_copy, &buf, &sz) == 0);
         assert_se(streq(buf, "foo bar bar bar foo\n"));

commit e45fc5e738b0b7700e8b4f3c4b25c58a49b44b27
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 19:14:08 2015 +0100

    man: bring machinectl man page up-to-date

diff --git a/man/machinectl.xml b/man/machinectl.xml
index ebe8e3b..91bdb5e 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -76,27 +76,31 @@
                                 <term><option>-p</option></term>
                                 <term><option>--property=</option></term>
 
-                                <listitem><para>When showing
-                                machine properties, limit the
-                                output to certain properties as
-                                specified by the argument. If not
-                                specified, all set properties are
-                                shown. The argument should be a
-                                property name, such as
-                                <literal>Name</literal>. If
-                                specified more than once, all
-                                properties with the specified names
-                                are shown.</para></listitem>
+                                <listitem><para>When showing machine
+                                or image properties, limit the output
+                                to certain properties as specified by
+                                the argument. If not specified, all
+                                set properties are shown. The argument
+                                should be a property name, such as
+                                <literal>Name</literal>. If specified
+                                more than once, all properties with
+                                the specified names are
+                                shown.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                                 <term><option>-a</option></term>
                                 <term><option>--all</option></term>
 
-                                <listitem><para>When showing
-                                machine properties, show all
-                                properties regardless of whether they are
-                                set or not.</para></listitem>
+                                <listitem><para>When showing machine
+                                or image properties, show all
+                                properties regardless of whether they
+                                are set or not.</para>
+
+                                <para>When listing VM or container
+                                images, do not suppress images
+                                beginning in a dot character
+                                (<literal>.</literal>).</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -208,16 +212,24 @@
                         <xi:include href="standard-options.xml" xpointer="version" />
                         <xi:include href="standard-options.xml" xpointer="no-pager" />
                 </variablelist>
+        </refsect1>
+
+        <refsect1>
+                <title>Commands</title>
 
                 <para>The following commands are understood:</para>
 
-                <variablelist>
+                <refsect2><title>Machine Commands</title><variablelist>
+
                         <varlistentry>
                                 <term><command>list</command></term>
 
                                 <listitem><para>List currently running
-                                virtual machines and containers.
-                                </para></listitem>
+                                (online) virtual machines and
+                                containers. To enumerate container
+                                images that can be started,
+                                use <command>list-images</command>
+                                (see below).</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -265,29 +277,91 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><command>start</command> <replaceable>NAME</replaceable>...</term>
+
+                                <listitem><para>Start a container as a
+                                system service, using
+                                <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+                                This starts
+                                <filename>systemd-nspawn at .service</filename>,
+                                instantiated for the specified machine
+                                name, similar to the effect of
+                                <command>systemctl start</command> on
+                                the service
+                                name. <command>systemd-nspawn</command>
+                                looks for a container image by the
+                                specified name in
+                                <filename>/var/lib/container</filename>
+                                and runs it. Use
+                                <command>list-images</command> (see
+                                below), for listing available
+                                container images to start.</para>
+
+                                <para>Note that
+                                <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+                                also interfaces with a variety of
+                                other container and VM managers,
+                                <command>systemd-nspawn</command> is
+                                just one implementation of it. Most of
+                                the commands available in
+                                <command>machinectl</command> may be
+                                used on containers or VMs controlled
+                                by other managers, not just
+                                <command>systemd-nspawn</command>. Starting
+                                VMs and container images on those
+                                managers requires manager-specific
+                                tools.</para>
+
+                                <para>To interactively start a
+                                container on the command line with
+                                full access to the container's
+                                console, please invoke
+                                <command>systemd-nspawn</command>
+                                directly. To stop a running container
+                                use <command>machinectl
+                                poweroff</command>, see
+                                below.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><command>login</command> <replaceable>NAME</replaceable></term>
 
-                                <listitem><para>Open a terminal login
+                                <listitem><para>Open an interactive terminal login
                                 session to a container. This will
                                 create a TTY connection to a specific
                                 container and asks for the execution of a
                                 getty on it. Note that this is only
                                 supported for containers running
                                 <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-                                as init system.</para></listitem>
+                                as init system.</para>
+
+                                <para>This command will open a full
+                                login prompt on the container, which
+                                then asks for username and
+                                password. Use
+                                <citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                                with the <option>--machine=</option>
+                                switch to invoke a single command,
+                                either interactively or in the
+                                background within a local
+                                container.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
-                                <term><command>reboot</command> <replaceable>NAME</replaceable>...</term>
-
-                                <listitem><para>Reboot one or more
-                                containers. This will trigger a reboot
-                                by sending SIGINT to the container's
-                                init process, which is roughly
-                                equivalent to pressing Ctrl+Alt+Del on
-                                a non-containerized system, and is
-                                compatible with containers running any
-                                init system.</para></listitem>
+                                <term><command>enable</command> <replaceable>NAME</replaceable>...</term>
+                                <term><command>disable</command> <replaceable>NAME</replaceable>...</term>
+
+                                <listitem><para>Enable or disable a
+                                container as a system service to start
+                                at system boot, using
+                                <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+                                This enables or disables
+                                <filename>systemd-nspawn at .service</filename>,
+                                instantiated for the specified machine
+                                name, similar to the effect of
+                                <command>systemctl enable</command> or
+                                <command>systemctl disable</command>
+                                on the service name.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -302,8 +376,38 @@
                                 not work on containers that do not run
                                 a
                                 <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>-compatible
-                                init system, such as
-                                sysvinit.</para></listitem>
+                                init system, such as sysvinit. Use
+                                <command>terminate</command> (see
+                                below) to immediately terminate a
+                                container or VM, without cleanly
+                                shutting it down.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>reboot</command> <replaceable>NAME</replaceable>...</term>
+
+                                <listitem><para>Reboot one or more
+                                containers. This will trigger a reboot
+                                by sending SIGINT to the container's
+                                init process, which is roughly
+                                equivalent to pressing Ctrl+Alt+Del on
+                                a non-containerized system, and is
+                                compatible with containers running any
+                                system manager.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>terminate</command> <replaceable>NAME</replaceable>...</term>
+
+                                <listitem><para>Immediately terminates
+                                a virtual machine or container,
+                                without cleanly shutting it down. This
+                                kills all processes of the virtual
+                                machine or container and deallocates
+                                all resources attached to that
+                                instance. Use
+                                <command>poweroff</command> to issue a
+                                clean shutdown request.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -322,17 +426,6 @@
                         </varlistentry>
 
                         <varlistentry>
-                                <term><command>terminate</command> <replaceable>NAME</replaceable>...</term>
-
-                                <listitem><para>Terminates a virtual
-                                machine or container. This kills all
-                                processes of the virtual machine or
-                                container and deallocates all
-                                resources attached to that
-                                instance.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
                                 <term><command>bind</command> <replaceable>NAME</replaceable> <replaceable>PATH</replaceable> [<replaceable>PATH</replaceable>]</term>
 
                                 <listitem><para>Bind mounts a
@@ -383,8 +476,122 @@
                                 omitted the same as the source path is
                                 used.</para></listitem>
                         </varlistentry>
+                </variablelist></refsect2>
 
-                </variablelist>
+                <refsect2><title>Image Commands</title><variablelist>
+
+                        <varlistentry>
+                                <term><command>list-images</command></term>
+
+                                <listitem><para>Show a list of locally
+                                installed container and VM
+                                images. This enumerates all raw disk
+                                images and container directories and
+                                subvolumes in
+                                <filename>/var/lib/container/</filename>. Use
+                                <command>start</command> (see above)
+                                to run a container off one of the
+                                listed images. Note that by default
+                                containers whose name begins with a
+                                dot (<literal>.</literal>) are not
+                                shown. To show these too, specify
+                                <option>--all</option>. Note that a
+                                special image <literal>.host</literal>
+                                always implicitly exists and refers to
+                                the image the host itself is booted
+                                from.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>image-status</command> <replaceable>NAME</replaceable>...</term>
+
+                                <listitem><para>Show terse status
+                                information about one or more
+                                container or VM images. This function
+                                is intended to generate human-readable
+                                output. Use
+                                <command>show-image</command> (see
+                                below) to generate computer-parsable
+                                output instead.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>show-image</command> <replaceable>NAME</replaceable>...</term>
+
+                                <listitem><para>Show properties of one
+                                or more registered virtual machine or
+                                container images, or the manager
+                                itself. If no argument is specified,
+                                properties of the manager will be
+                                shown. If an NAME is specified,
+                                properties of this virtual machine or
+                                container image are shown. By default,
+                                empty properties are suppressed. Use
+                                <option>--all</option> to show those
+                                too. To select specific properties to
+                                show, use
+                                <option>--property=</option>. This
+                                command is intended to be used
+                                whenever computer-parsable output is
+                                required. Use
+                                <command>image-status</command> if you
+                                are looking for formatted
+                                human-readable
+                                output.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>clone</command> <replaceable>NAME</replaceable> <replaceable>NAME</replaceable></term>
+
+                                <listitem><para>Clones a container or
+                                disk image. The arguments specify the
+                                name of the image to clone and the
+                                name of the newly cloned image. Note
+                                that plain directory container images
+                                are cloned into subvolume images with
+                                this command. Note that cloning a
+                                container or VM image is optimized for
+                                btrfs file systems, and might not be
+                                efficient on others, due to file
+                                system limitations.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>rename</command> <replaceable>NAME</replaceable> <replaceable>NAME</replaceable></term>
+
+                                <listitem><para>Renames a container or
+                                disk image. The arguments specify the
+                                name of the image to rename and the
+                                new name of the
+                                image.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>read-only</command> <replaceable>NAME</replaceable> [<replaceable>BOOL</replaceable>]</term>
+
+                                <listitem><para>Marks or (unmarks) a
+                                container or disk image
+                                read-only. Takes a VM or container
+                                image name, followed by a boolean as
+                                arguments. If the boolean is omitted,
+                                positive is implied, i.e. the image is
+                                marked read-only.</para></listitem>
+                        </varlistentry>
+
+
+                        <varlistentry>
+                                <term><command>remove</command> <replaceable>NAME</replaceable>...</term>
+
+                                <listitem><para>Removes one or more
+                                container or disk images. The special
+                                image <literal>.host</literal>, which
+                                refers to the host's own directory
+                                tree may not be
+                                removed.</para></listitem>
+                        </varlistentry>
+
+
+                </variablelist></refsect2>
 
         </refsect1>
 
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 939b648..dbfc245 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1760,8 +1760,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "  list                        List running VMs and containers\n"
                "  status NAME...              Show VM/container details\n"
                "  show NAME...                Show properties of one or more VMs/containers\n"
-               "  login NAME                  Get a login prompt on a container\n"
                "  start NAME...               Start container as a service\n"
+               "  login NAME                  Get a login prompt on a container\n"
                "  enable NAME...              Enable automatic container start at boot\n"
                "  disable NAME...             Disable automatic container start at boot\n"
                "  poweroff NAME...            Power off one or more containers\n"

commit b619ec8f83ee3f524dae1f4692b26731bbe68616
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 18:08:40 2015 +0100

    man: bring systemctl man page and --help text into the same order

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 3ac6f62..dd9fd99 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -386,7 +386,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
           querying the user for authentication for privileged
           operations.</para>
         </listitem>
-
       </varlistentry>
 
       <varlistentry>
@@ -993,6 +992,56 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
         </varlistentry>
 
         <varlistentry>
+          <term><command>reenable <replaceable>NAME</replaceable>...</command></term>
+
+          <listitem>
+            <para>Reenable one or more unit files, as specified on the
+            command line. This is a combination of
+            <command>disable</command> and <command>enable</command> and
+            is useful to reset the symlinks a unit is enabled with to
+            the defaults configured in the <literal>[Install]</literal>
+            section of the unit file.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><command>preset <replaceable>NAME</replaceable>...</command></term>
+
+          <listitem>
+            <para>Reset one or more unit files, as specified on the
+            command line, to the defaults configured in the preset
+            policy files. This has the same effect as
+            <command>disable</command> or <command>enable</command>,
+            depending how the unit is listed in the preset files.</para>
+
+            <para>Use <option>--preset-mode=</option> to control
+            whether units shall be enabled and disabled, or only
+            enabled, or only disabled.</para>
+
+            <para>For more information on the preset policy format,
+            see
+            <citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+            For more information on the concept of presets, please
+            consult the <ulink
+            url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
+            document.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><command>preset-all</command></term>
+
+          <listitem>
+            <para>Resets all installed unit files to the defaults
+            configured in the preset policy file (see above).</para>
+
+            <para>Use <option>--preset-mode=</option> to control
+            whether units shall be enabled and disabled, or only
+            enabled, or only disabled.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
           <term><command>is-enabled <replaceable>NAME</replaceable>...</command></term>
 
           <listitem>
@@ -1064,56 +1113,6 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
         </varlistentry>
 
         <varlistentry>
-          <term><command>reenable <replaceable>NAME</replaceable>...</command></term>
-
-          <listitem>
-            <para>Reenable one or more unit files, as specified on the
-            command line. This is a combination of
-            <command>disable</command> and <command>enable</command> and
-            is useful to reset the symlinks a unit is enabled with to
-            the defaults configured in the <literal>[Install]</literal>
-            section of the unit file.</para>
-          </listitem>
-        </varlistentry>
-
-        <varlistentry>
-          <term><command>preset <replaceable>NAME</replaceable>...</command></term>
-
-          <listitem>
-            <para>Reset one or more unit files, as specified on the
-            command line, to the defaults configured in the preset
-            policy files. This has the same effect as
-            <command>disable</command> or <command>enable</command>,
-            depending how the unit is listed in the preset files.</para>
-
-            <para>Use <option>--preset-mode=</option> to control
-            whether units shall be enabled and disabled, or only
-            enabled, or only disabled.</para>
-
-            <para>For more information on the preset policy format,
-            see
-            <citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
-            For more information on the concept of presets, please
-            consult the <ulink
-            url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
-            document.</para>
-          </listitem>
-        </varlistentry>
-
-        <varlistentry>
-          <term><command>preset-all</command></term>
-
-          <listitem>
-            <para>Resets all installed unit files to the defaults
-            configured in the preset policy file (see above).</para>
-
-            <para>Use <option>--preset-mode=</option> to control
-            whether units shall be enabled and disabled, or only
-            enabled, or only disabled.</para>
-          </listitem>
-        </varlistentry>
-
-        <varlistentry>
           <term><command>mask <replaceable>NAME</replaceable>...</command></term>
 
           <listitem>
@@ -1140,25 +1139,6 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
         </varlistentry>
 
         <varlistentry>
-          <term><command>add-wants <replaceable>TARGET</replaceable>
-          <replaceable>NAME</replaceable>...</command></term>
-          <term><command>add-requires <replaceable>TARGET</replaceable>
-          <replaceable>NAME</replaceable>...</command></term>
-
-          <listitem>
-            <para>Adds <literal>Wants=</literal> resp. <literal>Requires=</literal>
-            dependency to the specified <replaceable>TARGET</replaceable> for
-            one or more units. </para>
-
-            <para>This command honors <option>--system</option>,
-            <option>--user</option>, <option>--runtime</option> and
-            <option>--global</option> in a similar way as
-            <command>enable</command>.</para>
-
-          </listitem>
-        </varlistentry>
-
-        <varlistentry>
           <term><command>link <replaceable>FILENAME</replaceable>...</command></term>
 
           <listitem>
@@ -1173,20 +1153,21 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
         </varlistentry>
 
         <varlistentry>
-          <term><command>get-default</command></term>
+          <term><command>add-wants <replaceable>TARGET</replaceable>
+          <replaceable>NAME</replaceable>...</command></term>
+          <term><command>add-requires <replaceable>TARGET</replaceable>
+          <replaceable>NAME</replaceable>...</command></term>
 
           <listitem>
-            <para>Get the default target specified
-            via <filename>default.target</filename> link.</para>
-          </listitem>
-        </varlistentry>
+            <para>Adds <literal>Wants=</literal> resp. <literal>Requires=</literal>
+            dependency to the specified <replaceable>TARGET</replaceable> for
+            one or more units. </para>
 
-        <varlistentry>
-          <term><command>set-default <replaceable>NAME</replaceable></command></term>
+            <para>This command honors <option>--system</option>,
+            <option>--user</option>, <option>--runtime</option> and
+            <option>--global</option> in a similar way as
+            <command>enable</command>.</para>
 
-          <listitem>
-            <para>Set the default target to boot into. Command links
-            <filename>default.target</filename> to the given unit.</para>
           </listitem>
         </varlistentry>
 
@@ -1226,6 +1207,27 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             <filename>/run</filename>.</para>
           </listitem>
         </varlistentry>
+
+        <varlistentry>
+          <term><command>get-default</command></term>
+
+          <listitem>
+            <para>Return the default target to boot into. This returns
+            the target unit name <filename>default.target</filename>
+            is aliased (symlinked) to.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><command>set-default <replaceable>NAME</replaceable></command></term>
+
+          <listitem>
+            <para>Set the default target to boot into. This sets
+            (symlinks) the <filename>default.target</filename> alias
+            to the given target unit.</para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
     </refsect2>
 
@@ -1547,6 +1549,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             <quote>firmware over the air</quote> update.</para>
           </listitem>
         </varlistentry>
+
         <varlistentry>
           <term><command>kexec</command></term>
 
@@ -1560,6 +1563,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             immediately followed by the reboot.</para>
           </listitem>
         </varlistentry>
+
         <varlistentry>
           <term><command>exit</command></term>
 
@@ -1569,8 +1573,29 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             with the <option>--user</option> option) and will fail
             otherwise.</para>
           </listitem>
+        </varlistentry>
 
+        <varlistentry>
+          <term><command>switch-root <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></command></term>
+
+          <listitem>
+            <para>Switches to a different root directory and executes a
+            new system manager process below it. This is intended for
+            usage in initial RAM disks ("initrd"), and will transition
+            from the initrd's system manager process (a.k.a "init"
+            process) to the main system manager process. This call takes two
+            arguments: the directory that is to become the new root directory, and
+            the path to the new system manager binary below it to
+            execute as PID 1. If the latter is omitted or the empty
+            string, a systemd binary will automatically be searched for
+            and used as init. If the system manager path is omitted or
+            equal to the empty string, the state of the initrd's system
+            manager process is passed to the main system manager, which
+            allows later introspection of the state of the services
+            involved in the initrd boot.</para>
+          </listitem>
         </varlistentry>
+
         <varlistentry>
           <term><command>suspend</command></term>
 
@@ -1580,6 +1605,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             </para>
           </listitem>
         </varlistentry>
+
         <varlistentry>
           <term><command>hibernate</command></term>
 
@@ -1589,6 +1615,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             </para>
           </listitem>
         </varlistentry>
+
         <varlistentry>
           <term><command>hybrid-sleep</command></term>
 
@@ -1598,26 +1625,6 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             <filename>hybrid-sleep.target</filename> target.</para>
           </listitem>
         </varlistentry>
-        <varlistentry>
-          <term><command>switch-root <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></command></term>
-
-          <listitem>
-            <para>Switches to a different root directory and executes a
-            new system manager process below it. This is intended for
-            usage in initial RAM disks ("initrd"), and will transition
-            from the initrd's system manager process (a.k.a "init"
-            process) to the main system manager process. This call takes two
-            arguments: the directory that is to become the new root directory, and
-            the path to the new system manager binary below it to
-            execute as PID 1. If the latter is omitted or the empty
-            string, a systemd binary will automatically be searched for
-            and used as init. If the system manager path is omitted or
-            equal to the empty string, the state of the initrd's system
-            manager process is passed to the main system manager, which
-            allows later introspection of the state of the services
-            involved in the initrd boot.</para>
-          </listitem>
-        </varlistentry>
       </variablelist>
     </refsect2>
 
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index ded4943..74528dd 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -6075,7 +6075,7 @@ static void systemctl_help(void) {
                "                                  based on preset configuration\n"
                "  preset-all                      Enable/disable all unit files based on\n"
                "                                  preset configuration\n"
-               "  is-enabled NAME...              Check whether unit files are enabled\n\n"
+               "  is-enabled NAME...              Check whether unit files are enabled\n"
                "  mask NAME...                    Mask one or more units\n"
                "  unmask NAME...                  Unmask one or more units\n"
                "  link PATH...                    Link one or more units files into\n"
@@ -6084,10 +6084,9 @@ static void systemctl_help(void) {
                "                                  on specified one or more units\n"
                "  add-requires TARGET NAME...     Add 'Requires' dependency for the target\n"
                "                                  on specified one or more units\n"
-               "  get-default                     Get the name of the default target\n"
-               "  set-default NAME                Set the default target\n"
                "  edit NAME...                    Edit one or more unit files\n"
-               "\n"
+               "  get-default                     Get the name of the default target\n"
+               "  set-default NAME                Set the default target\n\n"
                "Machine Commands:\n"
                "  list-machines [PATTERN...]      List local containers and host\n\n"
                "Job Commands:\n"

commit 17cd091332040b9a3658db9374440fce7805ca54
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 18:07:25 2015 +0100

    man: add the same command sections to the man page as the --help text shows

diff --git a/man/loginctl.xml b/man/loginctl.xml
index 5ff9f75..7a6cc15 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -193,10 +193,15 @@
                         <xi:include href="standard-options.xml" xpointer="version" />
                         <xi:include href="standard-options.xml" xpointer="no-pager" />
                 </variablelist>
+        </refsect1>
+
+        <refsect1>
+                <title>Commands</title>
 
                 <para>The following commands are understood:</para>
 
-                <variablelist>
+                <refsect2><title>Session Commands</title><variablelist>
+
                         <varlistentry>
                                 <term><command>list-sessions</command></term>
 
@@ -291,7 +296,9 @@
                                 <option>--signal=</option> to select
                                 the signal to send.</para></listitem>
                         </varlistentry>
+                </variablelist></refsect2>
 
+                <refsect2><title>User Commands</title><variablelist>
                         <varlistentry>
                                 <term><command>list-users</command></term>
 
@@ -371,7 +378,9 @@
                                 <option>--signal=</option> to select
                                 the signal to send.</para></listitem>
                         </varlistentry>
+                </variablelist></refsect2>
 
+                <refsect2><title>Seat Commands</title><variablelist>
                         <varlistentry>
                                 <term><command>list-seats</command></term>
 
@@ -458,7 +467,7 @@
                                 and deallocates all runtime resources
                                 attached to them.</para></listitem>
                         </varlistentry>
-                </variablelist>
+                </variablelist></refsect2>
 
         </refsect1>
 

commit 079dac08c6a2725ce6e5ed2afa3f03d057c999c6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 15:33:46 2015 +0100

    systemctl,loginctl: start polkit agent for all polkit enabled operations

diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 57a0ab0..9f77903 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -50,8 +50,8 @@ static bool arg_legend = true;
 static const char *arg_kill_who = NULL;
 static int arg_signal = SIGTERM;
 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static bool arg_ask_password = true;
 static char *arg_host = NULL;
+static bool arg_ask_password = true;
 static unsigned arg_lines = 10;
 static OutputMode arg_output = OUTPUT_SHORT;
 
@@ -827,6 +827,8 @@ static int activate(sd_bus *bus, char **args, unsigned n) {
 
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         for (i = 1; i < n; i++) {
 
                 r = sd_bus_call_method (
@@ -856,6 +858,8 @@ static int kill_session(sd_bus *bus, char **args, unsigned n) {
 
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         if (!arg_kill_who)
                 arg_kill_who = "all";
 
@@ -921,6 +925,8 @@ static int terminate_user(sd_bus *bus, char **args, unsigned n) {
 
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         for (i = 1; i < n; i++) {
                 uid_t uid;
 
@@ -952,6 +958,8 @@ static int kill_user(sd_bus *bus, char **args, unsigned n) {
 
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         if (!arg_kill_who)
                 arg_kill_who = "all";
 
@@ -1036,6 +1044,8 @@ static int lock_sessions(sd_bus *bus, char **args, unsigned n) {
 
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         r = sd_bus_call_method (
                         bus,
                         "org.freedesktop.login1",
@@ -1057,6 +1067,8 @@ static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
 
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         for (i = 1; i < n; i++) {
 
                 r = sd_bus_call_method (
@@ -1077,6 +1089,7 @@ static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
 }
 
 static void help(void) {
+
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
                "Send control commands to or query the login manager.\n\n"
                "  -h --help                Show this help\n"
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 2c29f14..939b648 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -72,7 +72,6 @@ static OutputMode arg_output = OUTPUT_SHORT;
 
 static void pager_open_if_enabled(void) {
 
-        /* Cache result before we open the pager */
         if (arg_no_pager)
                 return;
 
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index b44c6d7..ded4943 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -176,7 +176,6 @@ static void ask_password_agent_open_if_enabled(void) {
         ask_password_agent_open();
 }
 
-#ifdef HAVE_LOGIND
 static void polkit_agent_open_if_enabled(void) {
 
         /* Open the polkit agent as a child process if necessary */
@@ -192,7 +191,6 @@ static void polkit_agent_open_if_enabled(void) {
 
         polkit_agent_open();
 }
-#endif
 
 static OutputFlags get_output_flags(void) {
         return
@@ -2706,6 +2704,7 @@ static int start_unit(sd_bus *bus, char **args) {
         assert(bus);
 
         ask_password_agent_open_if_enabled();
+        polkit_agent_open_if_enabled();
 
         if (arg_action == ACTION_SYSTEMCTL) {
                 enum action action;
@@ -3029,6 +3028,8 @@ static int kill_unit(sd_bus *bus, char **args) {
         assert(bus);
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         if (!arg_kill_who)
                 arg_kill_who = "all";
 
@@ -4601,6 +4602,8 @@ static int set_property(sd_bus *bus, char **args) {
         char **i;
         int r;
 
+        polkit_agent_open_if_enabled();
+
         r = sd_bus_message_new_method_call(
                         bus,
                         &m,
@@ -4661,6 +4664,8 @@ static int snapshot(sd_bus *bus, char **args) {
         const char *path;
         int r;
 
+        polkit_agent_open_if_enabled();
+
         if (strv_length(args) > 1)
                 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
         else
@@ -4723,6 +4728,8 @@ static int delete_snapshot(sd_bus *bus, char **args) {
 
         assert(args);
 
+        polkit_agent_open_if_enabled();
+
         r = expand_names(bus, args + 1, ".snapshot", &names);
         if (r < 0)
                 log_error_errno(r, "Failed to expand names: %m");
@@ -4766,6 +4773,8 @@ static int daemon_reload(sd_bus *bus, char **args) {
         const char *method;
         int r;
 
+        polkit_agent_open_if_enabled();
+
         if (arg_action == ACTION_RELOAD)
                 method = "Reload";
         else if (arg_action == ACTION_REEXEC)
@@ -4824,6 +4833,8 @@ static int reset_failed(sd_bus *bus, char **args) {
         if (strv_length(args) <= 1)
                 return daemon_reload(bus, args);
 
+        polkit_agent_open_if_enabled();
+
         r = expand_names(bus, args + 1, NULL, &names);
         if (r < 0)
                 log_error_errno(r, "Failed to expand names: %m");
@@ -5285,6 +5296,8 @@ static int enable_unit(sd_bus *bus, char **args) {
                 bool send_force = true, send_preset_mode = false;
                 const char *method;
 
+                polkit_agent_open_if_enabled();
+
                 if (streq(verb, "enable")) {
                         method = "EnableUnitFiles";
                         expect_carries_install_info = true;
@@ -5430,6 +5443,8 @@ static int add_dependency(sd_bus *bus, char **args) {
                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
 
+                polkit_agent_open_if_enabled();
+
                 r = sd_bus_message_new_method_call(
                                 bus,
                                 &m,
@@ -5493,6 +5508,8 @@ static int preset_all(sd_bus *bus, char **args) {
                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
 
+                polkit_agent_open_if_enabled();
+
                 r = sd_bus_message_new_method_call(
                                 bus,
                                 &m,

commit acf97e213e69a97e63ab8f7fad7ecd53608c757a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 15:23:54 2015 +0100

    machinectl: given that machinectl invokes a number of polkit enabled methods, start the polkit agent on terminals

diff --git a/man/machinectl.xml b/man/machinectl.xml
index baa0e17..ebe8e3b 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -109,6 +109,14 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><option>--no-ask-password</option></term>
+
+                                <listitem><para>Do not query the user
+                                for authentication for privileged
+                                operations.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><option>--kill-who=</option></term>
 
                                 <listitem><para>When used with
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 6180de1..2c29f14 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -38,6 +38,7 @@
 #include "util.h"
 #include "macro.h"
 #include "pager.h"
+#include "spawn-polkit-agent.h"
 #include "bus-util.h"
 #include "bus-error.h"
 #include "build.h"
@@ -65,6 +66,7 @@ static char *arg_host = NULL;
 static bool arg_read_only = false;
 static bool arg_mkdir = false;
 static bool arg_quiet = false;
+static bool arg_ask_password = true;
 static unsigned arg_lines = 10;
 static OutputMode arg_output = OUTPUT_SHORT;
 
@@ -77,6 +79,19 @@ static void pager_open_if_enabled(void) {
         pager_open(false);
 }
 
+static void polkit_agent_open_if_enabled(void) {
+
+        /* Open the polkit agent as a child process if necessary */
+
+        if (!arg_ask_password)
+                return;
+
+        if (arg_transport != BUS_TRANSPORT_LOCAL)
+                return;
+
+        polkit_agent_open();
+}
+
 static OutputFlags get_output_flags(void) {
         return
                 arg_all * OUTPUT_SHOW_ALL |
@@ -911,6 +926,8 @@ static int kill_machine(int argc, char *argv[], void *userdata) {
 
         assert(bus);
 
+        polkit_agent_open_if_enabled();
+
         if (!arg_kill_who)
                 arg_kill_who = "all";
 
@@ -956,6 +973,8 @@ static int terminate_machine(int argc, char *argv[], void *userdata) {
 
         assert(bus);
 
+        polkit_agent_open_if_enabled();
+
         for (i = 1; i < argc; i++) {
                 int r;
 
@@ -1345,6 +1364,8 @@ static int login_machine(int argc, char *argv[], void *userdata) {
                 return -ENOTSUP;
         }
 
+        polkit_agent_open_if_enabled();
+
         r = sd_event_default(&event);
         if (r < 0)
                 return log_error_errno(r, "Failed to get event loop: %m");
@@ -1375,7 +1396,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_set_allow_interactive_authorization(m, true);
+        r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -1434,6 +1455,8 @@ static int remove_image(int argc, char *argv[], void *userdata) {
 
         assert(bus);
 
+        polkit_agent_open_if_enabled();
+
         for (i = 1; i < argc; i++) {
                 r = sd_bus_call_method(
                                 bus,
@@ -1458,6 +1481,8 @@ static int rename_image(int argc, char *argv[], void *userdata) {
         sd_bus *bus = userdata;
         int r;
 
+        polkit_agent_open_if_enabled();
+
         r = sd_bus_call_method(
                         bus,
                         "org.freedesktop.machine1",
@@ -1480,6 +1505,8 @@ static int clone_image(int argc, char *argv[], void *userdata) {
         sd_bus *bus = userdata;
         int r;
 
+        polkit_agent_open_if_enabled();
+
         r = sd_bus_call_method(
                         bus,
                         "org.freedesktop.machine1",
@@ -1510,6 +1537,8 @@ static int read_only_image(int argc, char *argv[], void *userdata) {
                 }
         }
 
+        polkit_agent_open_if_enabled();
+
         r = sd_bus_call_method(
                         bus,
                         "org.freedesktop.machine1",
@@ -1535,6 +1564,8 @@ static int start_machine(int argc, char *argv[], void *userdata) {
 
         assert(bus);
 
+        polkit_agent_open_if_enabled();
+
         r = bus_wait_for_jobs_new(bus, &w);
         if (r < 0)
                 return log_oom();
@@ -1567,7 +1598,7 @@ static int start_machine(int argc, char *argv[], void *userdata) {
                 if (r < 0)
                         return bus_log_create_error(r);
 
-                r = sd_bus_message_set_allow_interactive_authorization(m, true);
+                r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -1607,6 +1638,8 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
 
         assert(bus);
 
+        polkit_agent_open_if_enabled();
+
         method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles";
 
         r = sd_bus_message_new_method_call(
@@ -1619,7 +1652,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_set_allow_interactive_authorization(m, true);
+        r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -1687,7 +1720,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_set_allow_interactive_authorization(m, true);
+        r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -1709,6 +1742,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --version                Show package version\n"
                "     --no-pager               Do not pipe output into a pager\n"
                "     --no-legend              Do not show the headers and footers\n"
+               "     --no-ask-password        Do not ask for system passwords\n"
                "  -H --host=[USER@]HOST       Operate on remote host\n"
                "  -M --machine=CONTAINER      Operate on local container\n"
                "  -p --property=NAME          Show only properties by this name\n"
@@ -1760,6 +1794,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_KILL_WHO,
                 ARG_READ_ONLY,
                 ARG_MKDIR,
+                ARG_NO_ASK_PASSWORD,
         };
 
         static const struct option options[] = {
@@ -1779,6 +1814,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "quiet",           no_argument,       NULL, 'q'                 },
                 { "lines",           required_argument, NULL, 'n'                 },
                 { "output",          required_argument, NULL, 'o'                 },
+                { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
                 {}
         };
 
@@ -1853,6 +1889,10 @@ static int parse_argv(int argc, char *argv[]) {
                         }
                         break;
 
+                case ARG_NO_ASK_PASSWORD:
+                        arg_ask_password = false;
+                        break;
+
                 case 'H':
                         arg_transport = BUS_TRANSPORT_REMOTE;
                         arg_host = optarg;
@@ -1938,6 +1978,7 @@ int main(int argc, char*argv[]) {
 
 finish:
         pager_close();
+        polkit_agent_close();
 
         strv_free(arg_property);
 

commit 8b0cc9a36c8f92f010f2e8465942d2cd7c580d78
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 15:09:12 2015 +0100

    machinectl: show most recent log output in "machinectl status", too

diff --git a/Makefile.am b/Makefile.am
index 420a567..e024748 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5078,6 +5078,8 @@ machinectl_SOURCES = \
 
 machinectl_LDADD = \
 	libsystemd-internal.la \
+	libsystemd-logs.la \
+	libsystemd-journal-internal.la \
 	libsystemd-shared.la
 
 rootbin_PROGRAMS += \
diff --git a/man/machinectl.xml b/man/machinectl.xml
index eef1740..baa0e17 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -165,6 +165,34 @@
                                 mount.</para></listitem>
                         </varlistentry>
 
+
+                        <varlistentry>
+                                <term><option>-n</option></term>
+                                <term><option>--lines=</option></term>
+
+                                <listitem><para>When used with
+                                <command>status</command>, controls
+                                the number of journal lines to show,
+                                counting from the most recent
+                                ones. Takes a positive integer
+                                argument. Defaults to 10.</para>
+                                </listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>-o</option></term>
+                                <term><option>--output=</option></term>
+
+                                <listitem><para>When used with
+                                <command>status</command>, controls
+                                the formatting of the journal entries
+                                that are shown. For the available
+                                choices, see
+                                <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+                                Defaults to
+                                <literal>short</literal>.</para></listitem>
+                        </varlistentry>
+
                         <xi:include href="user-system-options.xml" xpointer="host" />
                         <xi:include href="user-system-options.xml" xpointer="machine" />
 
@@ -189,12 +217,19 @@
 
                                 <listitem><para>Show terse runtime
                                 status information about one or more
-                                virtual machines and containers. This
-                                function is intended to generate
-                                human-readable output. If you are
-                                looking for computer-parsable output,
-                                use <command>show</command> instead.
-                                </para></listitem>
+                                virtual machines and containers,
+                                followed by the most recent log data
+                                from the journal. This function is
+                                intended to generate human-readable
+                                output. If you are looking for
+                                computer-parsable output, use
+                                <command>show</command> instead. Note
+                                that the log data shown is reported by
+                                the virtual machine or container
+                                manager, and frequently contains
+                                console output of the machine, but not
+                                necessarily journal contents of the
+                                machine itself.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index c80114c..6180de1 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -44,6 +44,7 @@
 #include "strv.h"
 #include "unit-name.h"
 #include "cgroup-show.h"
+#include "logs-show.h"
 #include "cgroup-util.h"
 #include "ptyfwd.h"
 #include "event-util.h"
@@ -64,6 +65,8 @@ static char *arg_host = NULL;
 static bool arg_read_only = false;
 static bool arg_mkdir = false;
 static bool arg_quiet = false;
+static unsigned arg_lines = 10;
+static OutputMode arg_output = OUTPUT_SHORT;
 
 static void pager_open_if_enabled(void) {
 
@@ -74,6 +77,15 @@ static void pager_open_if_enabled(void) {
         pager_open(false);
 }
 
+static OutputFlags get_output_flags(void) {
+        return
+                arg_all * OUTPUT_SHOW_ALL |
+                arg_full * OUTPUT_FULL_WIDTH |
+                (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+                on_tty() * OUTPUT_COLOR |
+                !arg_quiet * OUTPUT_WARN_CUTOFF;
+}
+
 typedef struct MachineInfo {
         const char *name;
         const char *class;
@@ -305,7 +317,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *path = NULL;
         const char *cgroup;
-        int r, output_flags;
+        int r;
         unsigned c;
 
         assert(bus);
@@ -342,17 +354,13 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
         if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
                 return 0;
 
-        output_flags =
-                arg_all * OUTPUT_SHOW_ALL |
-                arg_full * OUTPUT_FULL_WIDTH;
-
         c = columns();
         if (c > 18)
                 c -= 18;
         else
                 c = 0;
 
-        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, false, &leader, leader > 0, output_flags);
+        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, false, &leader, leader > 0, get_output_flags());
         return 0;
 }
 
@@ -467,7 +475,7 @@ typedef struct MachineStatusInfo {
         char *unit;
         char *root_directory;
         pid_t leader;
-        usec_t timestamp;
+        struct dual_timestamp timestamp;
         int *netif;
         unsigned n_netif;
 } MachineStatusInfo;
@@ -487,8 +495,8 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
         else
                 putchar('\n');
 
-        s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
-        s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
+        s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp.realtime);
+        s2 = format_timestamp(since2, sizeof(since2), i->timestamp.realtime);
 
         if (s1)
                 printf("\t   Since: %s; %s\n", s2, s1);
@@ -552,6 +560,22 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
         if (i->unit) {
                 printf("\t    Unit: %s\n", i->unit);
                 show_unit_cgroup(bus, i->unit, i->leader);
+
+                if (arg_transport == BUS_TRANSPORT_LOCAL) {
+
+                        show_journal_by_unit(
+                                        stdout,
+                                        i->unit,
+                                        arg_output,
+                                        0,
+                                        i->timestamp.monotonic,
+                                        arg_lines,
+                                        0,
+                                        get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+                                        SD_JOURNAL_LOCAL_ONLY,
+                                        true,
+                                        NULL);
+                }
         }
 }
 
@@ -579,15 +603,16 @@ static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
 static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
 
         static const struct bus_properties_map map[]  = {
-                { "Name",              "s",  NULL,          offsetof(MachineStatusInfo, name) },
-                { "Class",             "s",  NULL,          offsetof(MachineStatusInfo, class) },
-                { "Service",           "s",  NULL,          offsetof(MachineStatusInfo, service) },
-                { "Unit",              "s",  NULL,          offsetof(MachineStatusInfo, unit) },
-                { "RootDirectory",     "s",  NULL,          offsetof(MachineStatusInfo, root_directory) },
-                { "Leader",            "u",  NULL,          offsetof(MachineStatusInfo, leader) },
-                { "Timestamp",         "t",  NULL,          offsetof(MachineStatusInfo, timestamp) },
-                { "Id",                "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
-                { "NetworkInterfaces", "ai", map_netif,     0 },
+                { "Name",               "s",  NULL,          offsetof(MachineStatusInfo, name)                },
+                { "Class",              "s",  NULL,          offsetof(MachineStatusInfo, class)               },
+                { "Service",            "s",  NULL,          offsetof(MachineStatusInfo, service)             },
+                { "Unit",               "s",  NULL,          offsetof(MachineStatusInfo, unit)                },
+                { "RootDirectory",      "s",  NULL,          offsetof(MachineStatusInfo, root_directory)      },
+                { "Leader",             "u",  NULL,          offsetof(MachineStatusInfo, leader)              },
+                { "Timestamp",          "t",  NULL,          offsetof(MachineStatusInfo, timestamp.realtime)  },
+                { "TimestampMonotonic", "t",  NULL,          offsetof(MachineStatusInfo, timestamp.monotonic) },
+                { "Id",                 "ay", bus_map_id128, offsetof(MachineStatusInfo, id)                  },
+                { "NetworkInterfaces",  "ai", map_netif,     0                                                },
                 {}
         };
 
@@ -1693,7 +1718,11 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --kill-who=WHO           Who to send signal to\n"
                "  -s --signal=SIGNAL          Which signal to send\n"
                "     --read-only              Create read-only bind mount\n"
-               "     --mkdir                  Create directory before bind mounting, if missing\n\n"
+               "     --mkdir                  Create directory before bind mounting, if missing\n"
+               "  -n --lines=INTEGER          Number of journal entries to show\n"
+               "  -o --output=STRING          Change journal output mode (short,\n"
+               "                              short-monotonic, verbose, export, json,\n"
+               "                              json-pretty, json-sse, cat)\n\n"
                "Machine Commands:\n"
                "  list                        List running VMs and containers\n"
                "  status NAME...              Show VM/container details\n"
@@ -1748,6 +1777,8 @@ static int parse_argv(int argc, char *argv[]) {
                 { "read-only",       no_argument,       NULL, ARG_READ_ONLY       },
                 { "mkdir",           no_argument,       NULL, ARG_MKDIR           },
                 { "quiet",           no_argument,       NULL, 'q'                 },
+                { "lines",           required_argument, NULL, 'n'                 },
+                { "output",          required_argument, NULL, 'o'                 },
                 {}
         };
 
@@ -1756,7 +1787,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hp:als:H:M:q", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hp:als:H:M:qn:o:", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -1787,6 +1818,21 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_full = true;
                         break;
 
+                case 'n':
+                        if (safe_atou(optarg, &arg_lines) < 0) {
+                                log_error("Failed to parse lines '%s'", optarg);
+                                return -EINVAL;
+                        }
+                        break;
+
+                case 'o':
+                        arg_output = output_mode_from_string(optarg);
+                        if (arg_output < 0) {
+                                log_error("Unknown output '%s'.", optarg);
+                                return -EINVAL;
+                        }
+                        break;
+
                 case ARG_NO_PAGER:
                         arg_no_pager = true;
                         break;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 20c765e..b44c6d7 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -197,10 +197,10 @@ static void polkit_agent_open_if_enabled(void) {
 static OutputFlags get_output_flags(void) {
         return
                 arg_all * OUTPUT_SHOW_ALL |
+                arg_full * OUTPUT_FULL_WIDTH |
                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
                 on_tty() * OUTPUT_COLOR |
-                !arg_quiet * OUTPUT_WARN_CUTOFF |
-                arg_full * OUTPUT_FULL_WIDTH;
+                !arg_quiet * OUTPUT_WARN_CUTOFF;
 }
 
 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {

commit 3c7560019e623e6e0d03a860b4f19a3a8715feca
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 14:38:52 2015 +0100

    loginctl: show the 10 most recent log user/session log lines in "loginctl user-status" and "loginctl session-status"

diff --git a/Makefile.am b/Makefile.am
index 483feb3..420a567 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5539,6 +5539,8 @@ loginctl_SOURCES = \
 
 loginctl_LDADD = \
 	libsystemd-internal.la \
+	libsystemd-logs.la \
+	libsystemd-journal-internal.la \
 	libudev-internal.la \
 	libsystemd-shared.la
 
diff --git a/man/loginctl.xml b/man/loginctl.xml
index 749db92..5ff9f75 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -157,6 +157,35 @@
                                 <constant>SIGTERM</constant>.</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><option>-n</option></term>
+                                <term><option>--lines=</option></term>
+
+                                <listitem><para>When used with
+                                <command>user-status</command> and
+                                <command>session-status</command>,
+                                controls the number of journal lines
+                                to show, counting from the most recent
+                                ones. Takes a positive integer
+                                argument. Defaults to 10.</para>
+                                </listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>-o</option></term>
+                                <term><option>--output=</option></term>
+
+                                <listitem><para>When used with
+                                <command>user-status</command> and
+                                <command>session-status</command>,
+                                controls the formatting of the journal
+                                entries that are shown. For the
+                                available choices, see
+                                <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+                                Defaults to
+                                <literal>short</literal>.</para></listitem>
+                        </varlistentry>
+
                         <xi:include href="user-system-options.xml" xpointer="host" />
                         <xi:include href="user-system-options.xml" xpointer="machine" />
 
@@ -179,11 +208,12 @@
 
                                 <listitem><para>Show terse runtime
                                 status information about one or more
-                                sessions. This function is intended to
-                                generate human-readable output. If you
-                                are looking for computer-parsable
-                                output, use
-                                <command>show-session</command>
+                                sessions, followed by the most recent
+                                log data from the journal. This
+                                function is intended to generate
+                                human-readable output. If you are
+                                looking for computer-parsable output,
+                                use <command>show-session</command>
                                 instead.</para></listitem>
                         </varlistentry>
 
@@ -274,13 +304,14 @@
 
                                 <listitem><para>Show terse runtime
                                 status information about one or more
-                                logged in users. This function is
-                                intended to generate human-readable
-                                output. If you are looking for
-                                computer-parsable output, use
-                                <command>show-user</command> instead.
-                                Users may be specified by their
-                                usernames or numeric user IDs.
+                                logged in users, followed by the most
+                                recent log data from the journal. This
+                                function is intended to generate
+                                human-readable output. If you are
+                                looking for computer-parsable output,
+                                use <command>show-user</command>
+                                instead.  Users may be specified by
+                                their usernames or numeric user IDs.
                                 </para></listitem>
                         </varlistentry>
 
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index cc27544..57a0ab0 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -37,6 +37,7 @@
 #include "strv.h"
 #include "unit-name.h"
 #include "sysfs-show.h"
+#include "logs-show.h"
 #include "cgroup-show.h"
 #include "cgroup-util.h"
 #include "spawn-polkit-agent.h"
@@ -51,6 +52,8 @@ static int arg_signal = SIGTERM;
 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
 static bool arg_ask_password = true;
 static char *arg_host = NULL;
+static unsigned arg_lines = 10;
+static OutputMode arg_output = OUTPUT_SHORT;
 
 static void pager_open_if_enabled(void) {
 
@@ -73,6 +76,15 @@ static void polkit_agent_open_if_enabled(void) {
         polkit_agent_open();
 }
 
+static OutputFlags get_output_flags(void) {
+
+        return
+                arg_all * OUTPUT_SHOW_ALL |
+                arg_full * OUTPUT_FULL_WIDTH |
+                (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+                on_tty() * OUTPUT_COLOR;
+}
+
 static int list_sessions(sd_bus *bus, char **args, unsigned n) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
@@ -206,7 +218,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_free_ char *path = NULL;
         const char *cgroup;
-        int r, output_flags;
+        int r;
         unsigned c;
 
         assert(bus);
@@ -239,17 +251,13 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
         if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
                 return 0;
 
-        output_flags =
-                arg_all * OUTPUT_SHOW_ALL |
-                arg_full * OUTPUT_FULL_WIDTH;
-
         c = columns();
         if (c > 18)
                 c -= 18;
         else
                 c = 0;
 
-        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, false, &leader, leader > 0, output_flags);
+        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, false, &leader, leader > 0, get_output_flags());
         return 0;
 }
 
@@ -257,7 +265,7 @@ typedef struct SessionStatusInfo {
         const char *id;
         uid_t uid;
         const char *name;
-        usec_t timestamp;
+        struct dual_timestamp timestamp;
         unsigned int vtnr;
         const char *seat;
         const char *tty;
@@ -277,7 +285,7 @@ typedef struct SessionStatusInfo {
 typedef struct UserStatusInfo {
         uid_t uid;
         const char *name;
-        usec_t timestamp;
+        struct dual_timestamp timestamp;
         const char *state;
         char **sessions;
         const char *display;
@@ -357,24 +365,25 @@ static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_messag
 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
 
         static const struct bus_properties_map map[]  = {
-                { "Id",         "s", NULL, offsetof(SessionStatusInfo, id) },
-                { "Name",       "s", NULL, offsetof(SessionStatusInfo, name) },
-                { "TTY",        "s", NULL, offsetof(SessionStatusInfo, tty) },
-                { "Display",    "s", NULL, offsetof(SessionStatusInfo, display) },
-                { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
-                { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
-                { "Service",    "s", NULL, offsetof(SessionStatusInfo, service) },
-                { "Desktop",    "s", NULL, offsetof(SessionStatusInfo, desktop) },
-                { "Type",       "s", NULL, offsetof(SessionStatusInfo, type) },
-                { "Class",      "s", NULL, offsetof(SessionStatusInfo, class) },
-                { "Scope",      "s", NULL, offsetof(SessionStatusInfo, scope) },
-                { "State",      "s", NULL, offsetof(SessionStatusInfo, state) },
-                { "VTNr",       "u", NULL, offsetof(SessionStatusInfo, vtnr) },
-                { "Leader",     "u", NULL, offsetof(SessionStatusInfo, leader) },
-                { "Remote",     "b", NULL, offsetof(SessionStatusInfo, remote) },
-                { "Timestamp",  "t", NULL, offsetof(SessionStatusInfo, timestamp) },
-                { "User",       "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
-                { "Seat",       "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
+                { "Id",                  "s",    NULL,                     offsetof(SessionStatusInfo, id)                  },
+                { "Name",                "s",    NULL,                     offsetof(SessionStatusInfo, name)                },
+                { "TTY",                 "s",    NULL,                     offsetof(SessionStatusInfo, tty)                 },
+                { "Display",             "s",    NULL,                     offsetof(SessionStatusInfo, display)             },
+                { "RemoteHost",          "s",    NULL,                     offsetof(SessionStatusInfo, remote_host)         },
+                { "RemoteUser",          "s",    NULL,                     offsetof(SessionStatusInfo, remote_user)         },
+                { "Service",             "s",    NULL,                     offsetof(SessionStatusInfo, service)             },
+                { "Desktop",             "s",    NULL,                     offsetof(SessionStatusInfo, desktop)             },
+                { "Type",                "s",    NULL,                     offsetof(SessionStatusInfo, type)                },
+                { "Class",               "s",    NULL,                     offsetof(SessionStatusInfo, class)               },
+                { "Scope",               "s",    NULL,                     offsetof(SessionStatusInfo, scope)               },
+                { "State",               "s",    NULL,                     offsetof(SessionStatusInfo, state)               },
+                { "VTNr",                "u",    NULL,                     offsetof(SessionStatusInfo, vtnr)                },
+                { "Leader",              "u",    NULL,                     offsetof(SessionStatusInfo, leader)              },
+                { "Remote",              "b",    NULL,                     offsetof(SessionStatusInfo, remote)              },
+                { "Timestamp",           "t",    NULL,                     offsetof(SessionStatusInfo, timestamp.realtime)  },
+                { "TimestampMonotonic",  "t",    NULL,                     offsetof(SessionStatusInfo, timestamp.monotonic) },
+                { "User",                "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid)                 },
+                { "Seat",                "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat)                },
                 {}
         };
 
@@ -399,8 +408,8 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
         else
                 printf("%u\n", (unsigned) i.uid);
 
-        s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp);
-        s2 = format_timestamp(since2, sizeof(since2), i.timestamp);
+        s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
+        s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
 
         if (s1)
                 printf("\t   Since: %s; %s\n", s2, s1);
@@ -471,6 +480,22 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
         if (i.scope) {
                 printf("\t    Unit: %s\n", i.scope);
                 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
+
+                if (arg_transport == BUS_TRANSPORT_LOCAL) {
+
+                        show_journal_by_unit(
+                                        stdout,
+                                        i.scope,
+                                        arg_output,
+                                        0,
+                                        i.timestamp.monotonic,
+                                        arg_lines,
+                                        0,
+                                        get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+                                        SD_JOURNAL_LOCAL_ONLY,
+                                        true,
+                                        NULL);
+                }
         }
 
         return 0;
@@ -479,13 +504,14 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
 
         static const struct bus_properties_map map[]  = {
-                { "Name",       "s",     NULL, offsetof(UserStatusInfo, name) },
-                { "Slice",      "s",     NULL, offsetof(UserStatusInfo, slice) },
-                { "State",      "s",     NULL, offsetof(UserStatusInfo, state) },
-                { "UID",        "u",     NULL, offsetof(UserStatusInfo, uid) },
-                { "Timestamp",  "t",     NULL, offsetof(UserStatusInfo, timestamp) },
-                { "Display",    "(so)",  prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
-                { "Sessions",   "a(so)", prop_map_sessions_strv,   offsetof(UserStatusInfo, sessions) },
+                { "Name",               "s",     NULL,                     offsetof(UserStatusInfo, name)                },
+                { "Slice",              "s",     NULL,                     offsetof(UserStatusInfo, slice)               },
+                { "State",              "s",     NULL,                     offsetof(UserStatusInfo, state)               },
+                { "UID",                "u",     NULL,                     offsetof(UserStatusInfo, uid)                 },
+                { "Timestamp",          "t",     NULL,                     offsetof(UserStatusInfo, timestamp.realtime)  },
+                { "TimestampMonotonic", "t",     NULL,                     offsetof(UserStatusInfo, timestamp.monotonic) },
+                { "Display",            "(so)",  prop_map_first_of_struct, offsetof(UserStatusInfo, display)             },
+                { "Sessions",           "a(so)", prop_map_sessions_strv,   offsetof(UserStatusInfo, sessions)            },
                 {}
         };
 
@@ -510,8 +536,8 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
         else
                 printf("%u\n", (unsigned) i.uid);
 
-        s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp);
-        s2 = format_timestamp(since2, sizeof(since2), i.timestamp);
+        s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
+        s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
 
         if (s1)
                 printf("\t   Since: %s; %s\n", s2, s1);
@@ -538,6 +564,19 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
         if (i.slice) {
                 printf("\t    Unit: %s\n", i.slice);
                 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
+
+                show_journal_by_unit(
+                                stdout,
+                                i.slice,
+                                arg_output,
+                                0,
+                                i.timestamp.monotonic,
+                                arg_lines,
+                                0,
+                                get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+                                SD_JOURNAL_LOCAL_ONLY,
+                                true,
+                                NULL);
         }
 
 finish:
@@ -1051,7 +1090,10 @@ static void help(void) {
                "  -a --all                 Show all properties, including empty ones\n"
                "  -l --full                Do not ellipsize output\n"
                "     --kill-who=WHO        Who to send signal to\n"
-               "  -s --signal=SIGNAL       Which signal to send\n\n"
+               "  -s --signal=SIGNAL       Which signal to send\n"
+               "  -n --lines=INTEGER       Number of journal entries to show\n"
+               "  -o --output=STRING       Change journal output mode (short, short-monotonic,\n"
+               "                           verbose, export, json, json-pretty, json-sse, cat)\n\n"
                "Session Commands:\n"
                "  list-sessions            List sessions\n"
                "  session-status ID...     Show session status\n"
@@ -1104,6 +1146,8 @@ static int parse_argv(int argc, char *argv[]) {
                 { "host",            required_argument, NULL, 'H'                 },
                 { "machine",         required_argument, NULL, 'M'                 },
                 { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
+                { "lines",           required_argument, NULL, 'n'                 },
+                { "output",          required_argument, NULL, 'o'                 },
                 {}
         };
 
@@ -1112,7 +1156,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -1145,6 +1189,21 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_full = true;
                         break;
 
+                case 'n':
+                        if (safe_atou(optarg, &arg_lines) < 0) {
+                                log_error("Failed to parse lines '%s'", optarg);
+                                return -EINVAL;
+                        }
+                        break;
+
+                case 'o':
+                        arg_output = output_mode_from_string(optarg);
+                        if (arg_output < 0) {
+                                log_error("Unknown output '%s'.", optarg);
+                                return -EINVAL;
+                        }
+                        break;
+
                 case ARG_NO_PAGER:
                         arg_no_pager = true;
                         break;
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index dff0d30..b7a99d2 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -1234,12 +1234,12 @@ int show_journal_by_unit(
                 unsigned how_many,
                 uid_t uid,
                 OutputFlags flags,
-                bool system,
+                int journal_open_flags,
+                bool system_unit,
                 bool *ellipsized) {
 
         _cleanup_journal_close_ sd_journal*j = NULL;
         int r;
-        int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
 
         assert(mode >= 0);
         assert(mode < _OUTPUT_MODE_MAX);
@@ -1248,7 +1248,7 @@ int show_journal_by_unit(
         if (how_many <= 0)
                 return 0;
 
-        r = sd_journal_open(&j, jflags);
+        r = sd_journal_open(&j, journal_open_flags);
         if (r < 0)
                 return r;
 
@@ -1256,7 +1256,7 @@ int show_journal_by_unit(
         if (r < 0)
                 return r;
 
-        if (system)
+        if (system_unit)
                 r = add_matches_for_unit(j, unit);
         else
                 r = add_matches_for_user_unit(j, unit, uid);
diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h
index 187ee59..8d9641e 100644
--- a/src/shared/logs-show.h
+++ b/src/shared/logs-show.h
@@ -25,7 +25,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 
-#include "systemd/sd-journal.h"
+#include "sd-journal.h"
 
 #include "util.h"
 #include "output-mode.h"
@@ -58,7 +58,8 @@ int show_journal_by_unit(
                 unsigned how_many,
                 uid_t uid,
                 OutputFlags flags,
-                bool system,
+                int journal_open_flags,
+                bool system_unit,
                 bool *ellipsized);
 
 void json_escape(
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 86b5ae0..20c765e 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -194,6 +194,15 @@ static void polkit_agent_open_if_enabled(void) {
 }
 #endif
 
+static OutputFlags get_output_flags(void) {
+        return
+                arg_all * OUTPUT_SHOW_ALL |
+                (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+                on_tty() * OUTPUT_COLOR |
+                !arg_quiet * OUTPUT_WARN_CUTOFF |
+                arg_full * OUTPUT_FULL_WIDTH;
+}
+
 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
         assert(error);
 
@@ -3224,12 +3233,6 @@ static void print_status_info(
         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
         char since2[FORMAT_TIMESTAMP_MAX], *s2;
         const char *path;
-        int flags =
-                arg_all * OUTPUT_SHOW_ALL |
-                (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
-                on_tty() * OUTPUT_COLOR |
-                !arg_quiet * OUTPUT_WARN_CUTOFF |
-                arg_full * OUTPUT_FULL_WIDTH;
         char **t, **t2;
 
         assert(i);
@@ -3499,21 +3502,23 @@ static void print_status_info(
                         if (i->control_pid > 0)
                                 extra[k++] = i->control_pid;
 
-                        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
+                        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags());
                 }
         }
 
         if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
-                show_journal_by_unit(stdout,
-                                     i->id,
-                                     arg_output,
-                                     0,
-                                     i->inactive_exit_timestamp_monotonic,
-                                     arg_lines,
-                                     getuid(),
-                                     flags | OUTPUT_BEGIN_NEWLINE,
-                                     arg_scope == UNIT_FILE_SYSTEM,
-                                     ellipsized);
+                show_journal_by_unit(
+                                stdout,
+                                i->id,
+                                arg_output,
+                                0,
+                                i->inactive_exit_timestamp_monotonic,
+                                arg_lines,
+                                getuid(),
+                                get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+                                SD_JOURNAL_LOCAL_ONLY,
+                                arg_scope == UNIT_FILE_SYSTEM,
+                                ellipsized);
         }
 
         if (i->need_daemon_reload)
@@ -4377,13 +4382,6 @@ static int show_system_status(sd_bus *bus) {
 
         printf("   CGroup: %s\n", mi.control_group ?: "/");
         if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
-                int flags =
-                        arg_all * OUTPUT_SHOW_ALL |
-                        (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
-                        on_tty() * OUTPUT_COLOR |
-                        !arg_quiet * OUTPUT_WARN_CUTOFF |
-                        arg_full * OUTPUT_FULL_WIDTH;
-
                 static const char prefix[] = "           ";
                 unsigned c;
 
@@ -4393,7 +4391,7 @@ static int show_system_status(sd_bus *bus) {
                 else
                         c = 0;
 
-                show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
+                show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
         }
 
         free(mi.state);



More information about the systemd-commits mailing list