machinectl.c revision c7b7d4493aa03e9ef5fb1e670b8969a48aa494dd
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering This file is part of systemd.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Copyright 2013 Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is free software; you can redistribute it and/or modify it
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering under the terms of the GNU Lesser General Public License as published by
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (at your option) any later version.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is distributed in the hope that it will be useful, but
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Lesser General Public License for more details.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering You should have received a copy of the GNU Lesser General Public License
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic bool arg_all = false;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic bool arg_full = false;
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poetteringstatic bool arg_no_pager = false;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic bool arg_legend = true;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic bool arg_read_only = false;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic bool arg_mkdir = false;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic void pager_open_if_enabled(void) {
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering /* Cache result before we open the pager */
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering const char *name, *class, *service, *object;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering unsigned k = 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering "org.freedesktop.machine1",
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering "org.freedesktop.machine1.Manager",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering "ListMachines",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_error("Could not get machines: %s", bus_error_message(&error, -r));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering printf("%-32s %-9s %-16s\n", name, class, service);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_bus_message_exit_container(reply);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringtypedef struct ImageInfo {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering const ImageInfo *x = a, *y = b;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE");
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering "org.freedesktop.machine1",
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering "org.freedesktop.machine1.Manager",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbo)");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering while ((r = sd_bus_message_read(reply, "(ssbo)", &name, &type, &read_only, &object)) > 0) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_bus_message_exit_container(reply);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering printf("%-*s %-*s %-3s\n", (int) max_name, "NAME", (int) max_type, "TYPE", "RO");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (j = 0; j < n_images; j++) {
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering printf("\n%zu images listed.\n", n_images);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poetteringstatic int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (arg_transport == BUS_TRANSPORT_REMOTE)
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering "ControlGroup",
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering r = sd_bus_message_read(reply, "s", &cgroup);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poetteringstatic int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering "org.freedesktop.machine1",
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering "org.freedesktop.machine1.Manager",
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering "GetMachineAddresses",
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iay)");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering const void *a;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering r = sd_bus_message_read(reply, "i", &family);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = sd_bus_message_read_array(reply, 'y', &a, &sz);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = sd_bus_message_exit_container(reply);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
"/org/freedesktop/machine1",
NULL,
&reply,
return bus_log_parse_error(r);
pretty = v;
return bus_log_parse_error(r);
return bus_log_parse_error(r);
if (pretty)
typedef struct MachineStatusInfo {
char *name;
char *class;
char *service;
char *unit;
char *root_directory;
int *netif;
unsigned n_netif;
assert(i);
if (s1)
else if (s2)
if (i->leader > 0) {
if (i->service) {
if (i->class)
} else if (i->class)
if (i->root_directory)
if (i->n_netif > 0) {
for (c = 0; c < i->n_netif; c++) {
if (ifi < 0)
ifi = 0;
if (i->unit) {
static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
size_t l;
return -EBADMSG;
if (!i->netif)
return -ENOMEM;
path,
map,
&info);
if (*new_line)
*new_line = true;
if (*new_line)
*new_line = true;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
if (properties)
if (!arg_kill_who)
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
const char *object;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
r = sd_bus_get_property(
bus,
&error,
&reply2,
return bus_log_parse_error(r);
char *dest, *host_path, *container_path, *host_dirname, *host_basename, *container_dirname, *container_basename, *t;
bool copy_from;
return -EINVAL;
if (child < 0)
if (child == 0) {
int containerfd;
int mntfd;
if (mntfd < 0) {
if (containerfd < 0) {
if (copy_from)
return -EIO;
return -EIO;
const char *dest;
return -EINVAL;
return -ENOTSUP;
mount_slave_created = true;
goto finish;
mount_slave_mounted = true;
goto finish;
goto finish;
mount_tmp_created = true;
goto finish;
mount_tmp_mounted = true;
if (arg_read_only)
goto finish;
goto finish;
mount_outside_created = true;
goto finish;
mount_outside_mounted = true;
mount_tmp_mounted = false;
mount_tmp_created = false;
mount_slave_mounted = false;
mount_slave_created = false;
if (child < 0) {
goto finish;
if (child == 0) {
const char *mount_inside;
int mntfd;
if (mntfd < 0) {
if (arg_mkdir)
goto finish;
r = -EIO;
goto finish;
r = -EIO;
goto finish;
if (mount_tmp_mounted)
if (mount_tmp_created)
if (mount_slave_mounted)
if (mount_slave_created)
} control = {};
return -errno;
if (child < 0)
return -errno;
if (child == 0) {
if (master < 0)
return -EIO;
return -errno;
int *fds;
unsigned n_fds;
return -EIO;
if (master < 0)
return -EIO;
return master;
const char *pty, *p;
int r, ret = 0;
char last_char = 0;
return -ENOTSUP;
if (master < 0)
if (!pty)
return -EIO;
if (!getty)
return log_oom();
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
return ret;
" show NAME... Show properties of one or more VMs/containers\n"
" terminate NAME... Terminate one or more VMs/containers\n"
case ARG_VERSION:
return log_oom();
arg_all = true;
arg_all = true;
arg_full = true;
case ARG_NO_PAGER:
arg_no_pager = true;
case ARG_NO_LEGEND:
arg_legend = false;
case ARG_KILL_WHO:
if (arg_signal < 0) {
return -EINVAL;
case ARG_READ_ONLY:
arg_read_only = true;
case ARG_MKDIR:
arg_mkdir = true;
return -EINVAL;
log_open();
goto finish;
goto finish;
pager_close();