[systemd-commits] 3 commits - Makefile.am man/machinectl.xml src/cgroups-agent src/fsck src/initctl src/libsystemd-bus src/machine src/systemd src/update-utmp

Lennart Poettering lennart at kemper.freedesktop.org
Wed Oct 30 15:42:14 CET 2013


 Makefile.am                        |    2 
 man/machinectl.xml                 |   75 +++++++++----------
 src/cgroups-agent/cgroups-agent.c  |    2 
 src/fsck/fsck.c                    |    2 
 src/initctl/initctl.c              |    2 
 src/libsystemd-bus/bus-container.c |  128 ++++++++++++++++++++++++++++++++
 src/libsystemd-bus/bus-container.h |   26 ++++++
 src/libsystemd-bus/bus-internal.c  |   26 ++++++
 src/libsystemd-bus/bus-internal.h  |    3 
 src/libsystemd-bus/bus-socket.c    |    4 -
 src/libsystemd-bus/bus-socket.h    |    2 
 src/libsystemd-bus/bus-util.c      |   92 +++++------------------
 src/libsystemd-bus/bus-util.h      |    3 
 src/libsystemd-bus/sd-bus.c        |  145 +++++++++++++++++++++++++++++++++++--
 src/machine/machinectl.c           |   92 +++++++++++------------
 src/systemd/sd-bus.h               |    4 -
 src/update-utmp/update-utmp.c      |    2 
 17 files changed, 440 insertions(+), 170 deletions(-)

New commits:
commit 53755121e1c8ebd3db0330bc82965ecf9a986449
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 30 15:42:06 2013 +0100

    machinectl: we don't really just show information, we execute operations

diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 83c5da3..d9a1670 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -528,8 +528,8 @@ static int help(void) {
                "     --version           Show package version\n"
                "     --no-pager          Do not pipe output into a pager\n"
                "     --no-ask-password   Don't prompt for password\n"
-               "  -H --host=[USER@]HOST  Show information for remote host\n"
-               "  -M --machine=CONTAINER Show information for local container\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"
                "  -a --all               Show all properties, including empty ones\n"
                "  -l --full              Do not ellipsize output\n"

commit a7893c6b28772edbc7e1fea3c209caa54d465648
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 30 15:34:50 2013 +0100

    bus: add API call to create bus connection to the system bus of local containers
    
    Also, add support for this to machinectl, so that we can enumerate the
    machines that run inside a container. We must go deeper!

diff --git a/Makefile.am b/Makefile.am
index bd7f577..de9a4aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1947,6 +1947,8 @@ libsystemd_bus_la_SOURCES = \
 	src/libsystemd-bus/bus-socket.h \
 	src/libsystemd-bus/bus-kernel.c \
 	src/libsystemd-bus/bus-kernel.h \
+	src/libsystemd-bus/bus-container.c \
+	src/libsystemd-bus/bus-container.h \
 	src/libsystemd-bus/bus-message.c \
 	src/libsystemd-bus/bus-message.h \
 	src/libsystemd-bus/bus-signature.c \
diff --git a/man/machinectl.xml b/man/machinectl.xml
index 2ed9f2e..f2fa6ce 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -87,6 +87,42 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><option>--no-pager</option></term>
+
+                                <listitem><para>Do not pipe output into a
+                                pager.</para></listitem>
+                        </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>-H</option></term>
+                                <term><option>--host=</option></term>
+
+                                <listitem><para>Execute operation
+                                remotely. Specify a hostname, or
+                                username and hostname separated by <literal>@</literal>,
+                                to connect to. This will use SSH to
+                                talk to the remote machine manager
+                                instance.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>-M</option></term>
+                                <term><option>--machine=</option></term>
+
+                                <listitem><para>Execute operation on a
+                                local container. Specify a container
+                                name to connect to.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><option>-p</option></term>
                                 <term><option>--property=</option></term>
 
@@ -123,21 +159,6 @@
                         </varlistentry>
 
                         <varlistentry>
-                                <term><option>--no-pager</option></term>
-
-                                <listitem><para>Do not pipe output into a
-                                pager.</para></listitem>
-                        </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
@@ -167,26 +188,6 @@
                                 <constant>SIGTERM</constant>.</para></listitem>
                         </varlistentry>
 
-                        <varlistentry>
-                                <term><option>-H</option></term>
-                                <term><option>--host</option></term>
-
-                                <listitem><para>Execute operation
-                                remotely. Specify a hostname, or
-                                username and hostname separated by <literal>@</literal>,
-                                to connect to. This will use SSH to
-                                talk to the remote machine manager
-                                instance.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>-P</option></term>
-                                <term><option>--privileged</option></term>
-
-                                <listitem><para>Acquire privileges via
-                                PolicyKit before executing the
-                                operation.</para></listitem>
-                        </varlistentry>
                 </variablelist>
 
                 <para>The following commands are understood:</para>
@@ -293,8 +294,8 @@
                 <title>See Also</title>
                 <para>
                         <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+                        <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>
                 </para>
         </refsect1>
 
diff --git a/src/libsystemd-bus/bus-container.c b/src/libsystemd-bus/bus-container.c
new file mode 100644
index 0000000..eac1863
--- /dev/null
+++ b/src/libsystemd-bus/bus-container.c
@@ -0,0 +1,128 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "util.h"
+#include "fileio.h"
+#include "bus-internal.h"
+#include "bus-socket.h"
+#include "bus-container.h"
+
+int bus_container_connect(sd_bus *b) {
+        _cleanup_free_ char *p = NULL, *s = NULL, *ns = NULL, *root = NULL, *class = NULL;
+        _cleanup_close_ int nsfd = -1, rootfd = -1;
+        siginfo_t si;
+        pid_t leader, child;
+        int r;
+
+        assert(b);
+        assert(b->input_fd < 0);
+        assert(b->output_fd < 0);
+
+        p = strappend("/run/systemd/machines/", b->machine);
+        if (!p)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
+        if (r < 0)
+                return r;
+        if (!s)
+                return -EIO;
+
+        if (!streq_ptr(class, "container"))
+                return -EIO;
+
+        r = parse_pid(s, &leader);
+        if (r < 0)
+                return r;
+        if (leader <= 1)
+                return -EIO;
+
+        r = asprintf(&ns, "/proc/%lu/ns/mnt", (unsigned long) leader);
+        if (r < 0)
+                return -ENOMEM;
+
+        nsfd = open(ns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+        if (nsfd < 0)
+                return -errno;
+
+        r = asprintf(&root, "/proc/%lu/root", (unsigned long) leader);
+        if (r < 0)
+                return -ENOMEM;
+
+        rootfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+        if (rootfd < 0)
+                return -errno;
+
+        b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (b->input_fd < 0)
+                return -errno;
+
+        b->output_fd = b->input_fd;
+
+        r = bus_socket_setup(b);
+        if (r < 0)
+                return r;
+
+        child = fork();
+        if (child < 0)
+                return -errno;
+
+        if (child == 0) {
+                r = setns(nsfd, CLONE_NEWNS);
+                if (r < 0)
+                        _exit(255);
+
+                if (fchdir(rootfd) < 0)
+                        _exit(255);
+
+                if (chroot(".") < 0)
+                        _exit(255);
+
+
+                r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
+                if (r < 0) {
+                        if (errno == EINPROGRESS)
+                                _exit(1);
+
+                        _exit(255);
+                }
+
+                _exit(0);
+        }
+
+        r = wait_for_terminate(child, &si);
+        if (r < 0)
+                return r;
+
+        if (si.si_code != CLD_EXITED)
+                return -EIO;
+
+        if (si.si_status == 1)
+                return 1;
+
+        if (si.si_status != 0)
+                return -EIO;
+
+        return bus_socket_start_auth(b);
+}
diff --git a/src/libsystemd-bus/bus-container.h b/src/libsystemd-bus/bus-container.h
new file mode 100644
index 0000000..65f43ab
--- /dev/null
+++ b/src/libsystemd-bus/bus-container.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-bus.h"
+
+int bus_container_connect(sd_bus *b);
diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h
index 2ae7961..913f281 100644
--- a/src/libsystemd-bus/bus-internal.h
+++ b/src/libsystemd-bus/bus-internal.h
@@ -196,6 +196,7 @@ struct sd_bus {
         socklen_t sockaddr_size;
 
         char *kernel;
+        char *machine;
 
         sd_id128_t server_id;
 
diff --git a/src/libsystemd-bus/bus-socket.c b/src/libsystemd-bus/bus-socket.c
index b60facb..b7e816e 100644
--- a/src/libsystemd-bus/bus-socket.c
+++ b/src/libsystemd-bus/bus-socket.c
@@ -600,7 +600,7 @@ static int bus_socket_read_auth(sd_bus *b) {
         return 1;
 }
 
-static int bus_socket_setup(sd_bus *b) {
+int bus_socket_setup(sd_bus *b) {
         int enable;
         socklen_t l;
 
@@ -668,7 +668,7 @@ static int bus_socket_start_auth_client(sd_bus *b) {
         return bus_socket_write_auth(b);
 }
 
-static int bus_socket_start_auth(sd_bus *b) {
+int bus_socket_start_auth(sd_bus *b) {
         assert(b);
 
         b->state = BUS_AUTHENTICATING;
diff --git a/src/libsystemd-bus/bus-socket.h b/src/libsystemd-bus/bus-socket.h
index a9c43f8..c61b90f 100644
--- a/src/libsystemd-bus/bus-socket.h
+++ b/src/libsystemd-bus/bus-socket.h
@@ -23,9 +23,11 @@
 
 #include "sd-bus.h"
 
+int bus_socket_setup(sd_bus *b);
 int bus_socket_connect(sd_bus *b);
 int bus_socket_exec(sd_bus *b);
 int bus_socket_take_fd(sd_bus *b);
+int bus_socket_start_auth(sd_bus *b);
 
 int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx);
 int bus_socket_read_message(sd_bus *bus, sd_bus_message **m);
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index 383b035..f42d5d0 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -46,6 +46,7 @@
 #include "bus-signature.h"
 #include "bus-objects.h"
 #include "bus-util.h"
+#include "bus-container.h"
 
 static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
 
@@ -117,6 +118,7 @@ static void bus_free(sd_bus *b) {
         free(b->auth_buffer);
         free(b->address);
         free(b->kernel);
+        free(b->machine);
 
         free(b->exec_path);
         strv_free(b->exec_argv);
@@ -753,6 +755,45 @@ static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
         return 0;
 }
 
+static int parse_container_address(sd_bus *b, const char **p, char **guid) {
+        _cleanup_free_ char *machine = NULL;
+        int r;
+
+        assert(b);
+        assert(p);
+        assert(*p);
+        assert(guid);
+
+        while (**p != 0 && **p != ';') {
+                r = parse_address_key(p, "guid", guid);
+                if (r < 0)
+                        return r;
+                else if (r > 0)
+                        continue;
+
+                r = parse_address_key(p, "machine", &machine);
+                if (r < 0)
+                        return r;
+                else if (r > 0)
+                        continue;
+
+                skip_address_key(p);
+        }
+
+        if (!machine)
+                return -EINVAL;
+
+        free(b->machine);
+        b->machine = machine;
+        machine = NULL;
+
+        b->sockaddr.un.sun_family = AF_UNIX;
+        strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
+        b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/var/run/dbus/system_bus_socket") - 1;
+
+        return 0;
+}
+
 static void bus_reset_parsed_address(sd_bus *b) {
         assert(b);
 
@@ -765,6 +806,8 @@ static void bus_reset_parsed_address(sd_bus *b) {
         b->server_id = SD_ID128_NULL;
         free(b->kernel);
         b->kernel = NULL;
+        free(b->machine);
+        b->machine = NULL;
 }
 
 static int bus_parse_next_address(sd_bus *b) {
@@ -824,6 +867,14 @@ static int bus_parse_next_address(sd_bus *b) {
                                 return r;
 
                         break;
+                } else if (startswith(a, "x-container:")) {
+
+                        a += 12;
+                        r = parse_container_address(b, &a, &guid);
+                        if (r < 0)
+                                return r;
+
+                        break;
                 }
 
                 a = strchr(a, ';');
@@ -849,24 +900,32 @@ static int bus_start_address(sd_bus *b) {
         for (;;) {
                 sd_bus_close(b);
 
-                if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
+                if (b->exec_path) {
 
-                        r = bus_socket_connect(b);
+                        r = bus_socket_exec(b);
                         if (r >= 0)
                                 return r;
 
                         b->last_connect_error = -r;
+                } else if (b->kernel) {
 
-                } else if (b->exec_path) {
+                        r = bus_kernel_connect(b);
+                        if (r >= 0)
+                                return r;
 
-                        r = bus_socket_exec(b);
+                        b->last_connect_error = -r;
+
+                } else if (b->machine) {
+
+                        r = bus_container_connect(b);
                         if (r >= 0)
                                 return r;
 
                         b->last_connect_error = -r;
-                } else if (b->kernel) {
 
-                        r = bus_kernel_connect(b);
+                } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
+
+                        r = bus_socket_connect(b);
                         if (r >= 0)
                                 return r;
 
@@ -937,7 +996,7 @@ int sd_bus_start(sd_bus *bus) {
 
         if (bus->input_fd >= 0)
                 r = bus_start_fd(bus);
-        else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel)
+        else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine)
                 r = bus_start_address(bus);
         else
                 return -EINVAL;
@@ -1069,6 +1128,42 @@ int sd_bus_open_system_remote(const char *host, sd_bus **ret) {
         return 0;
 }
 
+int sd_bus_open_system_container(const char *machine, sd_bus **ret) {
+        _cleanup_free_ char *e = NULL;
+        sd_bus *bus;
+        char *p;
+        int r;
+
+        assert_return(machine, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        e = bus_address_escape(machine);
+        if (!e)
+                return -ENOMEM;
+
+        p = strjoin("x-container:machine=", e, NULL);
+        if (!p)
+                return -ENOMEM;
+
+        r = sd_bus_new(&bus);
+        if (r < 0) {
+                free(p);
+                return r;
+        }
+
+        bus->address = p;
+        bus->bus_client = true;
+
+        r = sd_bus_start(bus);
+        if (r < 0) {
+                bus_free(bus);
+                return r;
+        }
+
+        *ret = bus;
+        return 0;
+}
+
 void sd_bus_close(sd_bus *bus) {
         if (!bus)
                 return;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 241e360..83c5da3 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -47,12 +47,12 @@ static bool arg_no_pager = false;
 static const char *arg_kill_who = NULL;
 static int arg_signal = SIGTERM;
 static enum transport {
-        TRANSPORT_NORMAL,
-        TRANSPORT_SSH,
-} arg_transport = TRANSPORT_NORMAL;
+        TRANSPORT_LOCAL,
+        TRANSPORT_REMOTE,
+        TRANSPORT_CONTAINER
+} arg_transport = TRANSPORT_LOCAL;
 static bool arg_ask_password = true;
 static char *arg_host = NULL;
-static char *arg_user = NULL;
 
 static void pager_open_if_enabled(void) {
 
@@ -94,9 +94,6 @@ static int list_machines(sd_bus *bus, char **args, unsigned n) {
                 goto fail;
 
         while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
-                if (r < 0)
-                        goto fail;
-
                 printf("%-32s %-9s %-16s\n", name, class, service);
 
                 k++;
@@ -115,7 +112,7 @@ static int list_machines(sd_bus *bus, char **args, unsigned n) {
 
 fail:
         log_error("Failed to parse reply: %s", strerror(-r));
-        return -EIO;
+        return r;
 }
 
 static int show_scope_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
@@ -129,30 +126,28 @@ static int show_scope_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
         assert(bus);
         assert(unit);
 
-        if (arg_transport == TRANSPORT_SSH)
+        if (arg_transport == TRANSPORT_REMOTE)
                 return 0;
 
         path = unit_dbus_path_from_name(unit);
         if (!path)
                 return log_oom();
 
-        r = sd_bus_call_method(
+        r = sd_bus_get_property(
                         bus,
                         "org.freedesktop.systemd1",
                         path,
-                        "org.freedesktop.DBus.Properties",
-                        "Get",
+                        "org.freedesktop.systemd1.Scope",
+                        "ControlGroup",
                         &error,
                         &reply,
-                        "ss",
-                        "org.freedesktop.systemd1.Scope",
-                        "ControlGroup");
+                        "s");
         if (r < 0) {
                 log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
                 return r;
         }
 
-        r = sd_bus_message_read(reply, "v", "s", &cgroup);
+        r = sd_bus_message_read(reply, "s", &cgroup);
         if (r < 0) {
                 log_error("Failed to parse reply: %s", strerror(-r));
                 return r;
@@ -371,9 +366,6 @@ static int show_one(const char *verb, sd_bus *bus, const char *path, bool show_p
                 const char *name;
                 const char *contents;
 
-                if (r < 0)
-                        goto fail;
-
                 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
                 if (r < 0)
                         goto fail;
@@ -415,7 +407,7 @@ static int show_one(const char *verb, sd_bus *bus, const char *path, bool show_p
 
 fail:
         log_error("Failed to parse reply: %s", strerror(-r));
-        return -EIO;
+        return r;
 }
 
 static int show(sd_bus *bus, char **args, unsigned n) {
@@ -460,7 +452,7 @@ static int show(sd_bus *bus, char **args, unsigned n) {
                 r = sd_bus_message_read(reply, "o", &path);
                 if (r < 0) {
                         log_error("Failed to parse reply: %s", strerror(-r));
-                        return -EIO;
+                        return r;
                 }
 
                 r = show_one(args[0], bus, path, show_properties, &new_line);
@@ -534,14 +526,15 @@ static int help(void) {
                "Send control commands to or query the virtual machine and container registration manager.\n\n"
                "  -h --help              Show this help\n"
                "     --version           Show package version\n"
+               "     --no-pager          Do not pipe output into a pager\n"
+               "     --no-ask-password   Don't prompt for password\n"
+               "  -H --host=[USER@]HOST  Show information for remote host\n"
+               "  -M --machine=CONTAINER Show information for local container\n"
                "  -p --property=NAME     Show only properties by this name\n"
                "  -a --all               Show all properties, including empty ones\n"
-               "     --kill-who=WHO      Who to send signal to\n"
                "  -l --full              Do not ellipsize output\n"
-               "  -s --signal=SIGNAL     Which signal to send\n"
-               "     --no-ask-password   Don't prompt for password\n"
-               "  -H --host=[USER@]HOST  Show information for remote host\n"
-               "     --no-pager          Do not pipe output into a pager\n\n"
+               "     --kill-who=WHO      Who to send signal to\n"
+               "  -s --signal=SIGNAL     Which signal to send\n\n"
                "Commands:\n"
                "  list                   List running VMs and containers\n"
                "  status [NAME...]       Show VM/container status\n"
@@ -572,16 +565,17 @@ static int parse_argv(int argc, char *argv[]) {
                 { "kill-who",        required_argument, NULL, ARG_KILL_WHO        },
                 { "signal",          required_argument, NULL, 's'                 },
                 { "host",            required_argument, NULL, 'H'                 },
+                { "machine",         required_argument, NULL, 'M'                 },
                 { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
                 { NULL,              0,                 NULL, 0                   }
         };
 
-        int c;
+        int c, r;
 
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hp:als:H:P", options, NULL)) >= 0) {
+        while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0) {
 
                 switch (c) {
 
@@ -594,22 +588,16 @@ static int parse_argv(int argc, char *argv[]) {
                         puts(SYSTEMD_FEATURES);
                         return 0;
 
-                case 'p': {
-                        char **l;
-
-                        l = strv_append(arg_property, optarg);
-                        if (!l)
-                                return -ENOMEM;
-
-                        strv_free(arg_property);
-                        arg_property = l;
+                case 'p':
+                        r = strv_extend(&arg_property, optarg);
+                        if (r < 0)
+                                return log_oom();
 
                         /* If the user asked for a particular
                          * property, show it to him, even if it is
                          * empty. */
                         arg_all = true;
                         break;
-                }
 
                 case 'a':
                         arg_all = true;
@@ -640,8 +628,13 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'H':
-                        arg_transport = TRANSPORT_SSH;
-                        parse_user_at_host(optarg, &arg_user, &arg_host);
+                        arg_transport = TRANSPORT_REMOTE;
+                        arg_host = optarg;
+                        break;
+
+                case 'M':
+                        arg_transport = TRANSPORT_CONTAINER;
+                        arg_host = optarg;
                         break;
 
                 case '?':
@@ -741,7 +734,7 @@ static int machinectl_main(sd_bus *bus, int argc, char *argv[], const int r) {
 }
 
 int main(int argc, char*argv[]) {
-        int r, retval = EXIT_FAILURE;
+        int r, ret = EXIT_FAILURE;
         _cleanup_bus_unref_ sd_bus *bus = NULL;
 
         setlocale(LC_ALL, "");
@@ -752,28 +745,31 @@ int main(int argc, char*argv[]) {
         if (r < 0)
                 goto finish;
         else if (r == 0) {
-                retval = EXIT_SUCCESS;
+                ret = EXIT_SUCCESS;
                 goto finish;
         }
 
-        if (arg_transport == TRANSPORT_NORMAL)
+        if (arg_transport == TRANSPORT_LOCAL)
                 r = sd_bus_open_system(&bus);
-        else if (arg_transport == TRANSPORT_SSH)
+        else if (arg_transport == TRANSPORT_REMOTE)
                 r = sd_bus_open_system_remote(arg_host, &bus);
+        else if (arg_transport == TRANSPORT_CONTAINER)
+                r = sd_bus_open_system_container(arg_host, &bus);
         else
                 assert_not_reached("Uh, invalid transport...");
         if (r < 0) {
-                retval = EXIT_FAILURE;
+                log_error("Failed to connect to machined: %s", strerror(-r));
+                ret = EXIT_FAILURE;
                 goto finish;
         }
 
         r = machinectl_main(bus, argc, argv, r);
-        retval = r < 0 ? EXIT_FAILURE : r;
+        ret = r < 0 ? EXIT_FAILURE : r;
 
 finish:
         strv_free(arg_property);
 
         pager_close();
 
-        return retval;
+        return ret;
 }
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 7b6c86d..7163b0c 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -61,6 +61,7 @@ typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *path, char ***
 int sd_bus_open_user(sd_bus **ret);
 int sd_bus_open_system(sd_bus **ret);
 int sd_bus_open_system_remote(const char *host, sd_bus **ret);
+int sd_bus_open_system_container(const char *machine, sd_bus **ret);
 
 int sd_bus_new(sd_bus **ret);
 int sd_bus_set_address(sd_bus *bus, const char *address);

commit 0f8bd8debb0ff7f5bff7738841931f6c41e40bc1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 30 13:52:40 2013 +0100

    bus: move ssh support into public API of libsystem-bus

diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
index 256de1f..d8ae55a 100644
--- a/src/cgroups-agent/cgroups-agent.c
+++ b/src/cgroups-agent/cgroups-agent.c
@@ -44,7 +44,7 @@ int main(int argc, char *argv[]) {
          * this to avoid an activation loop when we start dbus when we
          * are called when the dbus service is shut down. */
 
-        r = bus_connect_system(&bus);
+        r = bus_open_system_systemd(&bus);
         if (r < 0) {
                 log_warning("Failed to get D-Bus connection: %s", strerror(-r));
                 return EXIT_FAILURE;
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 5c21c7e..3164d68 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -50,7 +50,7 @@ static void start_target(const char *target) {
 
         assert(target);
 
-        r = bus_connect_system(&bus);
+        r = bus_open_system_systemd(&bus);
         if (r < 0) {
                 log_error("Failed to get D-Bus connection: %s", strerror(-r));
                 return;
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index 3c59861..0000d6c 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -329,7 +329,7 @@ static int server_init(Server *s, unsigned n_sockets) {
                 s->n_fifos ++;
         }
 
-        r = bus_connect_system(&s->bus);
+        r = bus_open_system_systemd(&s->bus);
         if (r < 0) {
                 log_error("Failed to get D-Bus connection: %s", strerror(-r));
                 r = -EIO;
diff --git a/src/libsystemd-bus/bus-internal.c b/src/libsystemd-bus/bus-internal.c
index 942ac2b..0bea8ca 100644
--- a/src/libsystemd-bus/bus-internal.c
+++ b/src/libsystemd-bus/bus-internal.c
@@ -277,3 +277,29 @@ const char *bus_message_type_to_string(uint8_t u) {
         else
                 return NULL;
 }
+
+char *bus_address_escape(const char *v) {
+        const char *a;
+        char *r, *b;
+
+        r = new(char, strlen(v)*3+1);
+        if (!r)
+                return NULL;
+
+        for (a = v, b = r; *a; a++) {
+
+                if ((*a >= '0' && *a <= '9') ||
+                    (*a >= 'a' && *a <= 'z') ||
+                    (*a >= 'A' && *a <= 'Z') ||
+                    strchr("_-/.", *a))
+                        *(b++) = *a;
+                else {
+                        *(b++) = '%';
+                        *(b++) = hexchar(*a >> 4);
+                        *(b++) = hexchar(*a & 0xF);
+                }
+        }
+
+        *b = 0;
+        return r;
+}
diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h
index 5f8298b..2ae7961 100644
--- a/src/libsystemd-bus/bus-internal.h
+++ b/src/libsystemd-bus/bus-internal.h
@@ -289,6 +289,8 @@ int bus_next_address(sd_bus *bus);
 
 bool bus_pid_changed(sd_bus *bus);
 
+char *bus_address_escape(const char *v);
+
 #define OBJECT_PATH_FOREACH_PREFIX(prefix, path)                        \
         for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \
              _slash && !(_slash[(_slash) == (prefix)] = 0);             \
diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c
index 6a2fb04..53be009 100644
--- a/src/libsystemd-bus/bus-util.c
+++ b/src/libsystemd-bus/bus-util.c
@@ -380,26 +380,22 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
 }
 
 static int bus_check_peercred(sd_bus *c) {
-        int fd;
         struct ucred ucred;
         socklen_t l;
+        int fd;
 
         assert(c);
 
         fd = sd_bus_get_fd(c);
-
-        assert(fd >= 0);
+        if (fd < 0)
+                return fd;
 
         l = sizeof(struct ucred);
-        if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
-                log_error("SO_PEERCRED failed: %m");
+        if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
                 return -errno;
-        }
 
-        if (l != sizeof(struct ucred)) {
-                log_error("SO_PEERCRED returned wrong size.");
+        if (l != sizeof(struct ucred))
                 return -E2BIG;
-        }
 
         if (ucred.uid != 0 && ucred.uid != geteuid())
                 return -EPERM;
@@ -407,79 +403,37 @@ static int bus_check_peercred(sd_bus *c) {
         return 1;
 }
 
-int bus_connect_system(sd_bus **_bus) {
-        sd_bus *bus = NULL;
+int bus_open_system_systemd(sd_bus **_bus) {
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
         int r;
-        bool private = true;
 
         assert(_bus);
 
-        if (geteuid() == 0) {
-                /* If we are root, then let's talk directly to the
-                 * system instance, instead of going via the bus */
-
-                r = sd_bus_new(&bus);
-                if (r < 0)
-                        return r;
-
-                r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
-                if (r < 0)
-                        return r;
-
-                r = sd_bus_start(bus);
-                if (r < 0)
-                        return r;
-
-        } else {
-                r = sd_bus_open_system(&bus);
-                if (r < 0)
-                        return r;
-
-                private = false;
-        }
-
-        if (private) {
-                r = bus_check_peercred(bus);
-                if (r < 0) {
-                        sd_bus_unref(bus);
-
-                        return -EACCES;
-                }
-        }
-
-        *_bus = bus;
-        return 0;
-}
-
-int bus_connect_system_ssh(const char *host, sd_bus **_bus) {
-        sd_bus *bus;
-        char *p = NULL;
-        int r;
+        if (geteuid() != 0)
+                return sd_bus_open_system(_bus);
 
-        assert(_bus);
-        assert(host);
-
-        asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
-        if (!p)
-                return -ENOMEM;
+        /* If we are root, then let's talk directly to the system
+         * instance, instead of going via the bus */
 
-	r = sd_bus_new(&bus);
-	if (r < 0)
-		return r;
+        r = sd_bus_new(&bus);
+        if (r < 0)
+                return r;
 
-	r = sd_bus_set_address(bus, p);
-	if (r < 0)
-		return r;
+        r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
+        if (r < 0)
+                return r;
 
-	r = sd_bus_set_bus_client(bus, true);
-	if (r < 0)
-		return r;
+        r = sd_bus_start(bus);
+        if (r < 0)
+                return r;
 
-	r = sd_bus_start(bus);
+        r = bus_check_peercred(bus);
         if (r < 0)
                 return r;
 
         *_bus = bus;
+        bus = NULL;
+
         return 0;
 }
 
diff --git a/src/libsystemd-bus/bus-util.h b/src/libsystemd-bus/bus-util.h
index 5ddab2c..46e10b3 100644
--- a/src/libsystemd-bus/bus-util.h
+++ b/src/libsystemd-bus/bus-util.h
@@ -37,8 +37,7 @@ int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool i
 int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata);
 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry);
 
-int bus_connect_system(sd_bus **_bus);
-int bus_connect_system_ssh(const char *host, sd_bus **_bus);
+int bus_open_system_systemd(sd_bus **_bus);
 
 int bus_generic_print_property(const char *name, sd_bus_message *property, bool all);
 
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index 55d964e..383b035 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -1033,6 +1033,42 @@ fail:
         return r;
 }
 
+int sd_bus_open_system_remote(const char *host, sd_bus **ret) {
+        _cleanup_free_ char *e = NULL;
+        char *p = NULL;
+        sd_bus *bus;
+        int r;
+
+        assert_return(host, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        e = bus_address_escape(host);
+        if (!e)
+                return -ENOMEM;
+
+        p = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL);
+        if (!p)
+                return -ENOMEM;
+
+        r = sd_bus_new(&bus);
+        if (r < 0) {
+                free(p);
+                return r;
+        }
+
+        bus->address = p;
+        bus->bus_client = true;
+
+        r = sd_bus_start(bus);
+        if (r < 0) {
+                bus_free(bus);
+                return r;
+        }
+
+        *ret = bus;
+        return 0;
+}
+
 void sd_bus_close(sd_bus *bus) {
         if (!bus)
                 return;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 8795565..241e360 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -759,7 +759,7 @@ int main(int argc, char*argv[]) {
         if (arg_transport == TRANSPORT_NORMAL)
                 r = sd_bus_open_system(&bus);
         else if (arg_transport == TRANSPORT_SSH)
-                r = bus_connect_system_ssh(arg_host, &bus);
+                r = sd_bus_open_system_remote(arg_host, &bus);
         else
                 assert_not_reached("Uh, invalid transport...");
         if (r < 0) {
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index aa8caee..7b6c86d 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -58,8 +58,9 @@ typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *path, char ***
 
 /* Connections */
 
-int sd_bus_open_system(sd_bus **ret);
 int sd_bus_open_user(sd_bus **ret);
+int sd_bus_open_system(sd_bus **ret);
+int sd_bus_open_system_remote(const char *host, sd_bus **ret);
 
 int sd_bus_new(sd_bus **ret);
 int sd_bus_set_address(sd_bus *bus, const char *address);
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index f5c143d..61db1e9 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -299,7 +299,7 @@ int main(int argc, char *argv[]) {
             errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
                 log_error("Failed to connect to audit log: %m");
 #endif
-        r = bus_connect_system(&c.bus);
+        r = bus_open_system_systemd(&c.bus);
         if (r < 0) {
                 log_error("Failed to get D-Bus connection: %s", strerror(-r));
                 r = -EIO;



More information about the systemd-commits mailing list