machinectl.c revision 9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering/***
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering This file is part of systemd.
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering Copyright 2013 Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering systemd is free software; you can redistribute it and/or modify it
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering under the terms of the GNU Lesser General Public License as published by
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering (at your option) any later version.
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering systemd is distributed in the hope that it will be useful, but
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering Lesser General Public License for more details.
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering You should have received a copy of the GNU Lesser General Public License
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering***/
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <unistd.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <errno.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <string.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <getopt.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <pwd.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <locale.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <socket.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <fcntl.h>
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger#include "sd-bus.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "log.h"
93cc7779e0c121b75183920173f37cd1ee9d59cfThomas Hindoe Paaboel Andersen#include "util.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "macro.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "pager.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "bus-util.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "bus-error.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "build.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "strv.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "unit-name.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "cgroup-show.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "cgroup-util.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "ptyfwd.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic char **arg_property = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic bool arg_all = false;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic bool arg_full = false;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic bool arg_no_pager = false;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic const char *arg_kill_who = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic int arg_signal = SIGTERM;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic bool arg_ask_password = true;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic char *arg_host = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic void pager_open_if_enabled(void) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering /* Cache result before we open the pager */
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (arg_no_pager)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering pager_open(false);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic int list_machines(sd_bus *bus, char **args, unsigned n) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering const char *name, *class, *service, *object;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering unsigned k = 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering int r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering pager_open_if_enabled();
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = sd_bus_call_method(
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering bus,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.machine1",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "/org/freedesktop/machine1",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.machine1.Manager",
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering "ListMachines",
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering &error,
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering &reply,
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering "");
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering log_error("Could not get machines: %s", bus_error_message(&error, -r));
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (on_tty())
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering goto fail;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering printf("%-32s %-9s %-16s\n", name, class, service);
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering k++;
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering }
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering if (r < 0)
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering goto fail;
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering r = sd_bus_message_exit_container(reply);
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering if (r < 0)
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering goto fail;
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering if (on_tty())
6ad623a3f77e087e308f334525fd4046811f2a9aLennart Poettering printf("\n%u machines listed.\n", k);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringfail:
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering log_error("Failed to parse reply: %s", strerror(-r));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic int show_scope_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_free_ char *path = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering const char *cgroup;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering int r, output_flags;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering unsigned c;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering assert(bus);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering assert(unit);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (arg_transport == BUS_TRANSPORT_REMOTE)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering path = unit_dbus_path_from_name(unit);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (!path)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return log_oom();
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = sd_bus_get_property(
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering bus,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.systemd1",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering path,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.systemd1.Scope",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "ControlGroup",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering &error,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering &reply,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "s");
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = sd_bus_message_read(reply, "s", &cgroup);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering log_error("Failed to parse reply: %s", strerror(-r));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (isempty(cgroup))
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering output_flags =
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering arg_all * OUTPUT_SHOW_ALL |
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering arg_full * OUTPUT_FULL_WIDTH;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering c = columns();
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (c > 18)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering c -= 18;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering else
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering c = 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringtypedef struct MachineStatusInfo {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering char *name;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering sd_id128_t id;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering char *class;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering char *service;
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek char *scope;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering char *root_directory;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering pid_t leader;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering usec_t timestamp;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering} MachineStatusInfo;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering char since2[FORMAT_TIMESTAMP_MAX], *s2;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering assert(i);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering fputs(strna(i->name), stdout);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (!sd_id128_equal(i->id, SD_ID128_NULL))
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering else
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek putchar('\n');
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (s1)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\t Since: %s; %s\n", s2, s1);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering else if (s2)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\t Since: %s\n", s2);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (i->leader > 0) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_free_ char *t = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\t Leader: %u", (unsigned) i->leader);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering get_process_comm(i->leader, &t);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (t)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf(" (%s)", t);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering putchar('\n');
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (i->service) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\t Service: %s", i->service);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (i->class)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("; class %s", i->class);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering putchar('\n');
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering } else if (i->class)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\t Class: %s\n", i->class);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (i->root_directory)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\t Root: %s\n", i->root_directory);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (i->scope) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\t Unit: %s\n", i->scope);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering show_scope_cgroup(bus, i->scope, i->leader);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburgerstatic int show_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger MachineStatusInfo info = {};
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger static const struct bus_properties_map map[] = {
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "Scope", "s", NULL, offsetof(MachineStatusInfo, scope) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger {}
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger };
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger int r;
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger assert(path);
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger assert(new_line);
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger r = bus_map_all_properties(bus,
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger "org.freedesktop.machine1",
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger path,
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger map,
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger &info);
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger if (r < 0) {
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger log_error("Could not get properties: %s", strerror(-r));
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger return r;
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger }
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger if (*new_line)
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger printf("\n");
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger *new_line = true;
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger print_machine_status_info(bus, &info);
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger free(info.name);
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger free(info.class);
28cb17ef0281efc3a46e5d0e702b0b0ddeaafaa4Filipe Brandenburger free(info.service);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering free(info.scope);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering free(info.root_directory);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic int show_properties(sd_bus *bus, const char *path, bool *new_line) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering int r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (*new_line)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering printf("\n");
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering *new_line = true;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = bus_print_all_properties(bus, path, arg_property, arg_all);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering log_error("Could not get properties: %s", strerror(-r));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic int show(sd_bus *bus, char **args, unsigned n) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering int r = 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering unsigned i;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering bool properties, new_line = false;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering assert(bus);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering assert(args);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering properties = !strstr(args[0], "status");
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering pager_open_if_enabled();
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (properties && n <= 1) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering /* If no argument is specified, inspect the manager
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering * itself */
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = show_properties(bus, "/org/freedesktop/machine1", &new_line);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering log_error("Failed to query properties: %s", strerror(-r));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering for (i = 1; i < n; i++) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering const char *path = NULL;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering r = sd_bus_call_method(
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering bus,
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering "org.freedesktop.machine1",
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering "/org/freedesktop/machine1",
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering "org.freedesktop.machine1.Manager",
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering "GetMachine",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering &error,
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering &reply,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "s", args[i]);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering if (r < 0) {
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek return r;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering }
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering r = sd_bus_message_read(reply, "o", &path);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering if (r < 0) {
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering log_error("Failed to parse reply: %s", strerror(-r));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering break;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (properties)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = show_properties(bus, path, &new_line);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering else
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = show_info(args[0], bus, path, &new_line);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic int kill_machine(sd_bus *bus, char **args, unsigned n) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering unsigned i;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek assert(args);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering if (!arg_kill_who)
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering arg_kill_who = "all";
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering for (i = 1; i < n; i++) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering int r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = sd_bus_call_method(
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering bus,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.machine1",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "/org/freedesktop/machine1",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.machine1.Manager",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "KillMachine",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering &error,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering NULL,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "ssi", args[i], arg_kill_who, arg_signal);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0) {
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering log_error("Could not kill machine: %s", bus_error_message(&error, -r));
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering return 0;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering}
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poetteringstatic int terminate_machine(sd_bus *bus, char **args, unsigned n) {
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering unsigned i;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering assert(args);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering for (i = 1; i < n; i++) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering int r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = sd_bus_call_method(
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering bus,
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.machine1",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "/org/freedesktop/machine1",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "org.freedesktop.machine1.Manager",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering "TerminateMachine",
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering &error,
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek NULL,
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering "s", args[i]);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering if (r < 0) {
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering log_error("Could not terminate machine: %s", bus_error_message(&error, -r));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return r;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return 0;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering}
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic int openpt_in_namespace(pid_t pid, int flags) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_close_ int nsfd = -1, rootfd = -1;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_free_ char *ns = NULL, *root = NULL;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _cleanup_close_pipe_ int sock[2] = { -1, -1 };
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering struct msghdr mh;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering union {
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering struct cmsghdr cmsghdr;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(int))];
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering } control;
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek struct cmsghdr *cmsg;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering int master = -1, r;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering pid_t child;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering siginfo_t si;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering r = asprintf(&ns, "/proc/%lu/ns/mnt", (unsigned long) pid);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return -ENOMEM;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering nsfd = open(ns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (nsfd < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return -errno;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = asprintf(&root, "/proc/%lu/root", (unsigned long) pid);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return -ENOMEM;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering rootfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (rootfd < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return -errno;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sock) < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return -errno;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek zero(control);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering zero(mh);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering mh.msg_control = &control;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering mh.msg_controllen = sizeof(control);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering child = fork();
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (child < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return -errno;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (child == 0) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering close_nointr_nofail(sock[0]);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering sock[0] = -1;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = setns(nsfd, CLONE_NEWNS);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _exit(EXIT_FAILURE);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (fchdir(rootfd) < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _exit(EXIT_FAILURE);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (chroot(".") < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _exit(EXIT_FAILURE);
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering master = posix_openpt(flags);
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering if (master < 0)
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering _exit(EXIT_FAILURE);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering cmsg->cmsg_level = SOL_SOCKET;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering cmsg->cmsg_type = SCM_RIGHTS;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering cmsg->cmsg_len = CMSG_LEN(sizeof(int));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering memcpy(CMSG_DATA(cmsg), &master, sizeof(int));
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering mh.msg_controllen = cmsg->cmsg_len;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering r = sendmsg(sock[1], &mh, MSG_NOSIGNAL);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering close_nointr_nofail(master);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (r < 0)
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _exit(EXIT_FAILURE);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering _exit(EXIT_SUCCESS);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering }
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering close_nointr_nofail(sock[1]);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering sock[1] = -1;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (recvmsg(sock[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek return -errno;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg))
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering int *fds;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering unsigned n_fds;
2d49a208f8ad9d1c4e79fa4302451e35d06de707Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering fds = (int*) CMSG_DATA(cmsg);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering if (n_fds != 1) {
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering close_many(fds, n_fds);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering return -EIO;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev }
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev master = fds[0];
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev }
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev r = wait_for_terminate(child, &si);
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS || master < 0) {
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev if (master >= 0)
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev close_nointr_nofail(master);
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev return r < 0 ? r : -EIO;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev }
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev return master;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev}
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venevstatic int login_machine(sd_bus *bus, char **args, unsigned n) {
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *reply2 = NULL, *reply3 = NULL;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev _cleanup_bus_unref_ sd_bus *container_bus = NULL;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev _cleanup_close_ int master = -1;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev _cleanup_free_ char *getty = NULL;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev const char *path, *pty, *p;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev uint32_t leader;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev sigset_t mask;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev int r;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev assert(bus);
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev assert(args);
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev if (arg_transport != BUS_TRANSPORT_LOCAL) {
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev log_error("Login only support on local machines.");
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev return -ENOTSUP;
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev }
436dd70f5331ec541ebdd84e106abaa63203f6f1Hristo Venev
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"GetMachine",
&error,
&reply,
"s", args[1]);
if (r < 0) {
log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "o", &path);
if (r < 0) {
log_error("Failed to parse reply: %s", strerror(-r));
return r;
}
r = sd_bus_get_property(
bus,
"org.freedesktop.machine1",
path,
"org.freedesktop.machine1.Machine",
"Leader",
&error,
&reply2,
"u");
if (r < 0) {
log_error("Failed to retrieve PID of leader: %s", strerror(-r));
return r;
}
r = sd_bus_message_read(reply2, "u", &leader);
if (r < 0) {
log_error("Failed to parse reply: %s", strerror(-r));
return r;
}
master = openpt_in_namespace(leader, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
if (master < 0) {
log_error("Failed to acquire pseudo tty: %s", strerror(-master));
return master;
}
pty = ptsname(master);
if (!pty) {
log_error("Failed to get pty name: %m");
return -errno;
}
p = startswith(pty, "/dev/pts/");
if (!p) {
log_error("Invalid pty name %s.", pty);
return -EIO;
}
r = sd_bus_open_system_container(args[1], &container_bus);
if (r < 0) {
log_error("Failed to get container bus: %s", strerror(-r));
return r;
}
getty = strjoin("container-getty@", p, ".service", NULL);
if (!getty)
return log_oom();
if (unlockpt(master) < 0) {
log_error("Failed to unlock tty: %m");
return -errno;
}
r = sd_bus_call_method(container_bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
&error, &reply3,
"ss", getty, "replace");
if (r < 0) {
log_error("Failed to start getty service: %s", bus_error_message(&error, r));
return r;
}
assert_se(sigemptyset(&mask) == 0);
sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
log_info("Connected to container %s. Press ^] three times within 1s to exit session.", args[1]);
r = process_pty(master, &mask, 0, 0);
if (r < 0) {
log_error("Failed to process pseudo tty: %s", strerror(-r));
return r;
}
fputc('\n', stdout);
log_info("Connection to container %s terminated.", args[1]);
return 0;
}
static int help(void) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"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 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"
" --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"
" show [NAME...] Show properties of one or more VMs/containers\n"
" terminate [NAME...] Terminate one or more VMs/containers\n"
" kill [NAME...] Send signal to processes of a VM/container\n"
" login [NAME] Get a login prompt on a container\n",
program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_KILL_WHO,
ARG_NO_ASK_PASSWORD,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "property", required_argument, NULL, 'p' },
{ "all", no_argument, NULL, 'a' },
{ "full", no_argument, NULL, 'l' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "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, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0) {
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0;
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;
break;
case 'l':
arg_full = true;
break;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case ARG_NO_ASK_PASSWORD:
arg_ask_password = false;
break;
case ARG_KILL_WHO:
arg_kill_who = optarg;
break;
case 's':
arg_signal = signal_from_string_try_harder(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
return -EINVAL;
}
break;
case 'H':
arg_transport = BUS_TRANSPORT_REMOTE;
arg_host = optarg;
break;
case 'M':
arg_transport = BUS_TRANSPORT_CONTAINER;
arg_host = optarg;
break;
case '?':
return -EINVAL;
default:
log_error("Unknown option code %c", c);
return -EINVAL;
}
}
return 1;
}
static int machinectl_main(sd_bus *bus, int argc, char *argv[]) {
static const struct {
const char* verb;
const enum {
MORE,
LESS,
EQUAL
} argc_cmp;
const int argc;
int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
} verbs[] = {
{ "list", LESS, 1, list_machines },
{ "status", MORE, 2, show },
{ "show", MORE, 1, show },
{ "terminate", MORE, 2, terminate_machine },
{ "kill", MORE, 2, kill_machine },
{ "login", MORE, 2, login_machine },
};
int left;
unsigned i;
assert(argc >= 0);
assert(argv);
left = argc - optind;
if (left <= 0)
/* Special rule: no arguments means "list-sessions" */
i = 0;
else {
if (streq(argv[optind], "help")) {
help();
return 0;
}
for (i = 0; i < ELEMENTSOF(verbs); i++)
if (streq(argv[optind], verbs[i].verb))
break;
if (i >= ELEMENTSOF(verbs)) {
log_error("Unknown operation %s", argv[optind]);
return -EINVAL;
}
}
switch (verbs[i].argc_cmp) {
case EQUAL:
if (left != verbs[i].argc) {
log_error("Invalid number of arguments.");
return -EINVAL;
}
break;
case MORE:
if (left < verbs[i].argc) {
log_error("Too few arguments.");
return -EINVAL;
}
break;
case LESS:
if (left > verbs[i].argc) {
log_error("Too many arguments.");
return -EINVAL;
}
break;
default:
assert_not_reached("Unknown comparison operator.");
}
return verbs[i].dispatch(bus, argv + optind, left);
}
int main(int argc, char*argv[]) {
int r, ret = EXIT_FAILURE;
_cleanup_bus_unref_ sd_bus *bus = NULL;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r < 0)
goto finish;
else if (r == 0) {
ret = EXIT_SUCCESS;
goto finish;
}
r = bus_open_transport(arg_transport, arg_host, false, &bus);
if (r < 0) {
log_error("Failed to create bus connection: %s", strerror(-r));
ret = EXIT_FAILURE;
goto finish;
}
r = machinectl_main(bus, argc, argv);
ret = r < 0 ? EXIT_FAILURE : r;
finish:
strv_free(arg_property);
pager_close();
return ret;
}