chiark / gitweb /
bus: add API call to create bus connection to the system bus of local containers
authorLennart Poettering <lennart@poettering.net>
Wed, 30 Oct 2013 14:34:50 +0000 (15:34 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 30 Oct 2013 14:37:02 +0000 (15:37 +0100)
Also, add support for this to machinectl, so that we can enumerate the
machines that run inside a container. We must go deeper!

Makefile.am
man/machinectl.xml
src/libsystemd-bus/bus-container.c [new file with mode: 0644]
src/libsystemd-bus/bus-container.h [new file with mode: 0644]
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-socket.c
src/libsystemd-bus/bus-socket.h
src/libsystemd-bus/sd-bus.c
src/machine/machinectl.c
src/systemd/sd-bus.h

index bd7f577..de9a4aa 100644 (file)
@@ -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 \
index 2ed9f2e..f2fa6ce 100644 (file)
                         </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>
 
                         </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
                                 <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>
                 <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 (file)
index 0000000..eac1863
--- /dev/null
@@ -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 (file)
index 0000000..65f43ab
--- /dev/null
@@ -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);
index 2ae7961..913f281 100644 (file)
@@ -196,6 +196,7 @@ struct sd_bus {
         socklen_t sockaddr_size;
 
         char *kernel;
+        char *machine;
 
         sd_id128_t server_id;
 
index b60facb..b7e816e 100644 (file)
@@ -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;
index a9c43f8..c61b90f 100644 (file)
 
 #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);
index 383b035..f42d5d0 100644 (file)
@@ -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;
index 241e360..83c5da3 100644 (file)
@@ -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;
 }
index 7b6c86d..7163b0c 100644 (file)
@@ -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);