mirror of
https://github.com/systemd/systemd.git
synced 2024-12-13 04:03:35 +08:00
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!
This commit is contained in:
parent
0f8bd8debb
commit
a7893c6b28
@ -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 \
|
||||
|
@ -86,6 +86,42 @@
|
||||
string and exits.</para></listitem>
|
||||
</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>
|
||||
@ -122,21 +158,6 @@
|
||||
</listitem>
|
||||
</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>
|
||||
|
||||
@ -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>
|
||||
|
||||
|
128
src/libsystemd-bus/bus-container.c
Normal file
128
src/libsystemd-bus/bus-container.c
Normal file
@ -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);
|
||||
}
|
26
src/libsystemd-bus/bus-container.h
Normal file
26
src/libsystemd-bus/bus-container.h
Normal file
@ -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);
|
@ -196,6 +196,7 @@ struct sd_bus {
|
||||
socklen_t sockaddr_size;
|
||||
|
||||
char *kernel;
|
||||
char *machine;
|
||||
|
||||
sd_id128_t server_id;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
@ -823,6 +866,14 @@ static int bus_parse_next_address(sd_bus *b) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
} else if (startswith(a, "x-container:")) {
|
||||
|
||||
a += 12;
|
||||
r = parse_container_address(b, &a, &guid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -849,15 +900,7 @@ static int bus_start_address(sd_bus *b) {
|
||||
for (;;) {
|
||||
sd_bus_close(b);
|
||||
|
||||
if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
|
||||
|
||||
r = bus_socket_connect(b);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
b->last_connect_error = -r;
|
||||
|
||||
} else if (b->exec_path) {
|
||||
if (b->exec_path) {
|
||||
|
||||
r = bus_socket_exec(b);
|
||||
if (r >= 0)
|
||||
@ -871,6 +914,22 @@ static int bus_start_address(sd_bus *b) {
|
||||
return r;
|
||||
|
||||
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->sockaddr.sa.sa_family != AF_UNSPEC) {
|
||||
|
||||
r = bus_socket_connect(b);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
b->last_connect_error = -r;
|
||||
}
|
||||
|
||||
r = bus_parse_next_address(b);
|
||||
@ -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;
|
||||
|
@ -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"
|
||||
" -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-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"
|
||||
" --no-pager Do not pipe output into a pager\n\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"
|
||||
" -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"
|
||||
"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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user