machinectl.c revision d538bfc71331d2e48363283decd77a61599021db
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2013 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <string.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <getopt.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <pwd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <locale.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <fcntl.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <netinet/in.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <arpa/inet.h>
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering#include <net/if.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/mount.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include <libgen.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#undef basename
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-bus.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "macro.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "pager.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "spawn-polkit-agent.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "bus-util.h"
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#include "bus-error.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "build.h"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering#include "strv.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "unit-name.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "cgroup-show.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "logs-show.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "cgroup-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "ptyfwd.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "event-util.h"
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen#include "path-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "copy.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "verbs.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic char **arg_property = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_all = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_full = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_no_pager = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_legend = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char *arg_kill_who = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int arg_signal = SIGTERM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic char *arg_host = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_read_only = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_mkdir = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_quiet = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_ask_password = true;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic unsigned arg_lines = 10;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic OutputMode arg_output = OUTPUT_SHORT;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void pager_open_if_enabled(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_no_pager)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen pager_open(false);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic void polkit_agent_open_if_enabled(void) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* Open the polkit agent as a child process if necessary */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!arg_ask_password)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_transport != BUS_TRANSPORT_LOCAL)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen polkit_agent_open();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic OutputFlags get_output_flags(void) {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_all * OUTPUT_SHOW_ALL |
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen arg_full * OUTPUT_FULL_WIDTH |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering on_tty() * OUTPUT_COLOR |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !arg_quiet * OUTPUT_WARN_CUTOFF;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poetteringtypedef struct MachineInfo {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *name;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *class;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *service;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering} MachineInfo;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersenstatic int compare_machine_info(const void *a, const void *b) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen const MachineInfo *x = a, *y = b;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return strcmp(x->name, y->name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_free_ MachineInfo *machines = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *name, *class, *service, *object;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering size_t n_machines = 0, n_allocated = 0, j;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_bus *bus = userdata;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering assert(bus);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering pager_open_if_enabled();
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = sd_bus_call_method(
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bus,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.machine1",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering "/org/freedesktop/machine1",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.machine1.Manager",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "ListMachines",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering &error,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering &reply,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering "");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Could not get machines: %s", bus_error_message(&error, -r));
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return bus_log_parse_error(r);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering size_t l;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1))
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return log_oom();
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering machines[n_machines].name = name;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering machines[n_machines].class = class;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering machines[n_machines].service = service;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering l = strlen(name);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (l > max_name)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering max_name = l;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering l = strlen(class);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (l > max_class)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering max_class = l;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering l = strlen(service);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (l > max_service)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering max_service = l;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering n_machines ++;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return bus_log_parse_error(r);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_message_exit_container(reply);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return bus_log_parse_error(r);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (arg_legend)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering printf("%-*s %-*s %-*s\n",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_name, "MACHINE",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_class, "CLASS",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_service, "SERVICE");
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering for (j = 0; j < n_machines; j++)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering printf("%-*s %-*s %-*s\n",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_name, machines[j].name,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_class, machines[j].class,
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering (int) max_service, machines[j].service);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (arg_legend)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering printf("\n%zu machines listed.\n", n_machines);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering return 0;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringtypedef struct ImageInfo {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const char *name;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering const char *type;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering bool read_only;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering usec_t crtime;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering usec_t mtime;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering uint64_t size;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering} ImageInfo;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering const ImageInfo *x = a, *y = b;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return strcmp(x->name, y->name);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("SIZE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering _cleanup_free_ ImageInfo *images = NULL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering size_t n_images = 0, n_allocated = 0, j;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const char *name, *type, *object;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering sd_bus *bus = userdata;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering uint64_t crtime, mtime, size;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int read_only, r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(bus);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering pager_open_if_enabled();
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_call_method(
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering bus,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "org.freedesktop.machine1",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "/org/freedesktop/machine1",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "org.freedesktop.machine1.Manager",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "ListImages",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering &error,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering &reply,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return bus_log_parse_error(r);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering size_t l;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (name[0] == '.' && !arg_all)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering continue;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return log_oom();
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering images[n_images].name = name;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering images[n_images].type = type;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering images[n_images].read_only = read_only;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering images[n_images].crtime = crtime;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering images[n_images].mtime = mtime;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering images[n_images].size = size;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering l = strlen(name);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (l > max_name)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering max_name = l;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering l = strlen(type);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (l > max_type)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering max_type = l;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (crtime != 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (l > max_crtime)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_crtime = l;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (mtime != 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l > max_mtime)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_mtime = l;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (size != (uint64_t) -1) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (l > max_size)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_size = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering n_images++;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_exit_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_legend)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%-*s %-*s %-3s %-*s %-*s %-*s\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_name, "NAME",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_type, "TYPE",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "RO",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_size, "SIZE",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_crtime, "CREATED",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_mtime, "MODIFIED");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (j = 0; j < n_images; j++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_name, images[j].name,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_type, images[j].type,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_highlight_off() : "",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_legend)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\n%zu images listed.\n", n_images);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *path = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *cgroup;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering int r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering unsigned c;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(bus);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(unit);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (arg_transport == BUS_TRANSPORT_REMOTE)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering path = unit_dbus_path_from_name(unit);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (!path)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return log_oom();
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = sd_bus_get_property(
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering bus,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "org.freedesktop.systemd1",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering path,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "ControlGroup",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering &error,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering &reply,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "s");
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (r < 0) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_read(reply, "s", &cgroup);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return bus_log_parse_error(r);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (isempty(cgroup))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering c = columns();
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (c > 18)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering c -= 18;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering else
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering c = 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return 0;
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek}
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering int r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(bus);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(name);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(prefix);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(prefix2);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_call_method(bus,
a6c616024db23fef34152c1432892824a07799ccLennart Poettering "org.freedesktop.machine1",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "/org/freedesktop/machine1",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "org.freedesktop.machine1.Manager",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "GetMachineAddresses",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering NULL,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering &reply,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "s", name);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (r < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iay)");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
a6c616024db23fef34152c1432892824a07799ccLennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int family;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const void *a;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t sz;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_read(reply, "i", &family);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_read_array(reply, 'y', &a, &sz);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(prefix, stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (family == AF_INET6 && ifi > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%%%i", ifi);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputc('\n', stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_exit_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (prefix != prefix2)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering prefix = prefix2;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_exit_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *k, *v, *pretty = NULL;
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(name);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(prefix);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(bus,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "/org/freedesktop/machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1.Manager",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "GetMachineOSRelease",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering NULL,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers &reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "s", name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_enter_container(reply, 'a', "{ss}");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (streq(k, "PRETTY_NAME"))
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers pretty = v;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_exit_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (pretty)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen printf("%s%s\n", prefix, pretty);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersentypedef struct MachineStatusInfo {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *name;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_id128_t id;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *class;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *service;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *unit;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *root_directory;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen pid_t leader;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct dual_timestamp timestamp;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering int *netif;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering unsigned n_netif;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering} MachineStatusInfo;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char since2[FORMAT_TIMESTAMP_MAX], *s2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int ifi = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fputs(strna(i->name), stdout);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!sd_id128_equal(i->id, SD_ID128_NULL))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering putchar('\n');
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp.realtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s2 = format_timestamp(since2, sizeof(since2), i->timestamp.realtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s1)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Since: %s; %s\n", s2, s1);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen else if (s2)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen printf("\t Since: %s\n", s2);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (i->leader > 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_free_ char *t = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen printf("\t Leader: %u", (unsigned) i->leader);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen get_process_comm(i->leader, &t);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (t)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen printf(" (%s)", t);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen putchar('\n');
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i->service) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Service: %s", i->service);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (i->class)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering printf("; class %s", i->class);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering putchar('\n');
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering } else if (i->class)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering printf("\t Class: %s\n", i->class);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (i->root_directory)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering printf("\t Root: %s\n", i->root_directory);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i->n_netif > 0) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering unsigned c;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs("\t Iface:", stdout);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering for (c = 0; c < i->n_netif; c++) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering char name[IF_NAMESIZE+1] = "";
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (if_indextoname(i->netif[c], name)) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering fputc(' ', stdout);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering fputs(name, stdout);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (ifi < 0)
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering ifi = i->netif[c];
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering else
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering ifi = 0;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering } else
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering printf(" %i", i->netif[c]);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering fputc('\n', stdout);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering print_addresses(bus, i->name, ifi,
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering "\t Address: ",
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering "\t ");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering print_os_release(bus, i->name, "\t OS: ");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (i->unit) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering printf("\t Unit: %s\n", i->unit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering show_unit_cgroup(bus, i->unit, i->leader);
3d94f76c99da13e5603831d0b278f8c8c21bcb02Lennart Poettering
a4475f577bd0daf762d6c3b4e58bc484e0cb74afLennart Poettering if (arg_transport == BUS_TRANSPORT_LOCAL) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering show_journal_by_unit(
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering stdout,
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek i->unit,
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek arg_output,
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek 0,
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek i->timestamp.monotonic,
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek arg_lines,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 0,
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen get_output_flags() | OUTPUT_BEGIN_NEWLINE,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering SD_JOURNAL_LOCAL_ONLY,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering true,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering NULL);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering }
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poetteringstatic int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering MachineStatusInfo *i = userdata;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering size_t l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const void *v;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_cc(sizeof(int32_t) == sizeof(int));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r == 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EBADMSG;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->n_netif = l / sizeof(int32_t);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->netif = memdup(v, l);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!i->netif)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ENOMEM;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering static const struct bus_properties_map map[] = {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp.realtime) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) },
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "NetworkInterfaces", "ai", map_netif, 0 },
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering {}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering };
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering MachineStatusInfo info = {};
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int r;
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering assert(verb);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(path);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = bus_map_all_properties(bus,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "org.freedesktop.machine1",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering path,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering map,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering &info);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*new_line)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\n");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *new_line = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering print_machine_status_info(bus, &info);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering free(info.name);
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering free(info.class);
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering free(info.service);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.unit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.root_directory);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.netif);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int show_machine_properties(sd_bus *bus, const char *path, bool *new_line) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(path);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*new_line)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\n");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *new_line = true;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error_errno(r, "Could not get properties: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int show_machine(int argc, char *argv[], void *userdata) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bool properties, new_line = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_bus *bus = userdata;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r = 0, i;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering properties = !strstr(argv[0], "status");
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering pager_open_if_enabled();
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (properties && argc <= 1) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* If no argument is specified, inspect the manager
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * itself */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = show_machine_properties(bus, "/org/freedesktop/machine1", &new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (i = 1; i < argc; i++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const char *path = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_bus_call_method(
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bus,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "org.freedesktop.machine1",
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering "/org/freedesktop/machine1",
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering "org.freedesktop.machine1.Manager",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "GetMachine",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering &error,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering &reply,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "s", argv[i]);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_bus_message_read(reply, "o", &path);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return bus_log_parse_error(r);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (properties)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = show_machine_properties(bus, path, &new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = show_machine_info(argv[0], bus, path, &new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
3db729cb8e6822114e9323f4041dcdc080f2fb3cJason A. Donenfeld return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringtypedef struct ImageStatusInfo {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *name;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *path;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *type;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int read_only;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering usec_t crtime;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering usec_t mtime;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering uint64_t size;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering uint64_t limit;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering uint64_t size_exclusive;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering uint64_t limit_exclusive;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering} ImageStatusInfo;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char bs[FORMAT_BYTES_MAX], *s3;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char bs_exclusive[FORMAT_BYTES_MAX], *s4;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(i);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->name) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering fputs(i->name, stdout);
a6c616024db23fef34152c1432892824a07799ccLennart Poettering putchar('\n');
a6c616024db23fef34152c1432892824a07799ccLennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->type)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Type: %s\n", i->type);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->path)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Path: %s\n", i->path);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t RO: %s%s%s\n",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->read_only ? ansi_highlight_red() : "",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->read_only ? "read-only" : "writable",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->read_only ? ansi_highlight_off() : "");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->crtime);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->crtime);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s1 && s2)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Created: %s; %s\n", s2, s1);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (s2)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Created: %s\n", s2);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->mtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->mtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s1 && s2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\tModified: %s; %s\n", s2, s1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (s2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\tModified: %s\n", s2);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen s3 = format_bytes(bs, sizeof(bs), i->size);
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering s4 = i->size_exclusive != i->size ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->size_exclusive) : NULL;
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering if (s3 && s4)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Size: %s (exclusive: %s)\n", s3, s4);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (s3)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Size: %s\n", s3);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->limit);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s3 && s4)
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek printf("\t Limit: %s (exclusive: %s)\n", s3, s4);
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek else if (s3)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering printf("\t Limit: %s\n", s3);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering}
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poetteringstatic int show_image_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering static const struct bus_properties_map map[] = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Name", "s", NULL, offsetof(ImageStatusInfo, name) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Path", "s", NULL, offsetof(ImageStatusInfo, path) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Type", "s", NULL, offsetof(ImageStatusInfo, type) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Size", "t", NULL, offsetof(ImageStatusInfo, size) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "SizeExclusive", "t", NULL, offsetof(ImageStatusInfo, size_exclusive) },
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering {}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ImageStatusInfo info = {};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(verb);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(new_line);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_map_all_properties(bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering path,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering map,
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*new_line)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *new_line = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering print_image_status_info(bus, &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.type);
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_image_properties(sd_bus *bus, const char *path, bool *new_line) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(bus);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(path);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(new_line);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*new_line)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *new_line = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error_errno(r, "Could not get properties: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_image(int argc, char *argv[], void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool properties, new_line = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus *bus = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r = 0, i;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen assert(bus);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen properties = !strstr(argv[0], "status");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pager_open_if_enabled();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (properties && argc <= 1) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If no argument is specified, inspect the manager
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * itself */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 1; i < argc; i++) {
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering const char *path = NULL;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = sd_bus_call_method(
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering bus,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering "org.freedesktop.machine1",
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering "/org/freedesktop/machine1",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering "org.freedesktop.machine1.Manager",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "GetImage",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "s", argv[i]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Could not get path to image: %s", bus_error_message(&error, -r));
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(reply, "o", &path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (properties)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = show_image_properties(bus, path, &new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = show_image_info(argv[0], bus, path, &new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int kill_machine(int argc, char *argv[], void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus *bus = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering polkit_agent_open_if_enabled();
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!arg_kill_who)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering arg_kill_who = "all";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 1; i < argc; i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1.Manager",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "KillMachine",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering NULL,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "ssi", argv[i], arg_kill_who, arg_signal);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Could not kill machine: %s", bus_error_message(&error, -r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int reboot_machine(int argc, char *argv[], void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_kill_who = "leader";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_signal = SIGINT; /* sysvinit + systemd */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return kill_machine(argc, argv, userdata);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int poweroff_machine(int argc, char *argv[], void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_kill_who = "leader";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_signal = SIGRTMIN+4; /* only systemd */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return kill_machine(argc, argv, userdata);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int terminate_machine(int argc, char *argv[], void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus *bus = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering polkit_agent_open_if_enabled();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 1; i < argc; i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1.Manager",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "TerminateMachine",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering NULL,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "s", argv[i]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Could not terminate machine: %s", bus_error_message(&error, -r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int machine_get_leader(sd_bus *bus, const char *name, pid_t *ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *reply2 = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *object;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint32_t leader;
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering assert(name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(ret);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_call_method(
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "/org/freedesktop/machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1.Manager",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "GetMachine",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply,
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering "s", name);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering if (r < 0) {
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
}
r = sd_bus_message_read(reply, "o", &object);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_get_property(
bus,
"org.freedesktop.machine1",
object,
"org.freedesktop.machine1.Machine",
"Leader",
&error,
&reply2,
"u");
if (r < 0)
return log_error_errno(r, "Failed to retrieve PID of leader: %m");
r = sd_bus_message_read(reply2, "u", &leader);
if (r < 0)
return bus_log_parse_error(r);
*ret = leader;
return 0;
}
static int copy_files(int argc, char *argv[], void *userdata) {
char *dest, *host_path, *container_path, *host_dirname, *host_basename, *container_dirname, *container_basename, *t;
_cleanup_close_ int hostfd = -1;
sd_bus *bus = userdata;
pid_t child, leader;
bool copy_from;
siginfo_t si;
int r;
assert(bus);
copy_from = streq(argv[0], "copy-from");
dest = argv[3] ?: argv[2];
host_path = strdupa(copy_from ? dest : argv[2]);
container_path = strdupa(copy_from ? argv[2] : dest);
if (!path_is_absolute(container_path)) {
log_error("Container path not absolute.");
return -EINVAL;
}
t = strdup(host_path);
host_basename = basename(t);
host_dirname = dirname(host_path);
t = strdup(container_path);
container_basename = basename(t);
container_dirname = dirname(container_path);
r = machine_get_leader(bus, argv[1], &leader);
if (r < 0)
return r;
hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
if (r < 0)
return log_error_errno(errno, "Failed to open source directory: %m");
child = fork();
if (child < 0)
return log_error_errno(errno, "Failed to fork(): %m");
if (child == 0) {
int containerfd;
const char *q;
int mntfd;
q = procfs_file_alloca(leader, "ns/mnt");
mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (mntfd < 0) {
log_error_errno(errno, "Failed to open mount namespace of leader: %m");
_exit(EXIT_FAILURE);
}
if (setns(mntfd, CLONE_NEWNS) < 0) {
log_error_errno(errno, "Failed to join namespace of leader: %m");
_exit(EXIT_FAILURE);
}
containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
if (containerfd < 0) {
log_error_errno(errno, "Failed top open destination directory: %m");
_exit(EXIT_FAILURE);
}
if (copy_from)
r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true);
else
r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true);
if (r < 0) {
log_error_errno(errno, "Failed to copy tree: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(child, &si);
if (r < 0)
return log_error_errno(r, "Failed to wait for client: %m");
if (si.si_code != CLD_EXITED) {
log_error("Client died abnormally.");
return -EIO;
}
if (si.si_status != EXIT_SUCCESS)
return -EIO;
return 0;
}
static int bind_mount(int argc, char *argv[], void *userdata) {
char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
sd_bus *bus = userdata;
pid_t child, leader;
const char *dest;
siginfo_t si;
bool mount_slave_created = false, mount_slave_mounted = false,
mount_tmp_created = false, mount_tmp_mounted = false,
mount_outside_created = false, mount_outside_mounted = false;
int r;
assert(bus);
/* One day, when bind mounting /proc/self/fd/n works across
* namespace boundaries we should rework this logic to make
* use of it... */
dest = argv[3] ?: argv[2];
if (!path_is_absolute(dest)) {
log_error("Destination path not absolute.");
return -EINVAL;
}
p = strappenda("/run/systemd/nspawn/propagate/", argv[1], "/");
if (access(p, F_OK) < 0) {
log_error("Container does not allow propagation of mount points.");
return -ENOTSUP;
}
r = machine_get_leader(bus, argv[1], &leader);
if (r < 0)
return r;
/* Our goal is to install a new bind mount into the container,
possibly read-only. This is irritatingly complex
unfortunately, currently.
First, we start by creating a private playground in /tmp,
that we can mount MS_SLAVE. (Which is necessary, since
MS_MOUNT cannot be applied to mounts with MS_SHARED parent
mounts.) */
if (!mkdtemp(mount_slave))
return log_error_errno(errno, "Failed to create playground: %m");
mount_slave_created = true;
if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
r = log_error_errno(errno, "Failed to make bind mount: %m");
goto finish;
}
mount_slave_mounted = true;
if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
r = log_error_errno(errno, "Failed to remount slave: %m");
goto finish;
}
/* Second, we mount the source directory to a directory inside
of our MS_SLAVE playground. */
mount_tmp = strappenda(mount_slave, "/mount");
if (mkdir(mount_tmp, 0700) < 0) {
r = log_error_errno(errno, "Failed to create temporary mount: %m");
goto finish;
}
mount_tmp_created = true;
if (mount(argv[2], mount_tmp, NULL, MS_BIND, NULL) < 0) {
r = log_error_errno(errno, "Failed to overmount: %m");
goto finish;
}
mount_tmp_mounted = true;
/* Third, we remount the new bind mount read-only if requested. */
if (arg_read_only)
if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
r = log_error_errno(errno, "Failed to mark read-only: %m");
goto finish;
}
/* Fourth, we move the new bind mount into the propagation
* directory. This way it will appear there read-only
* right-away. */
mount_outside = strappenda("/run/systemd/nspawn/propagate/", argv[1], "/XXXXXX");
if (!mkdtemp(mount_outside)) {
r = log_error_errno(errno, "Cannot create propagation directory: %m");
goto finish;
}
mount_outside_created = true;
if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
r = log_error_errno(errno, "Failed to move: %m");
goto finish;
}
mount_outside_mounted = true;
mount_tmp_mounted = false;
(void) rmdir(mount_tmp);
mount_tmp_created = false;
(void) umount(mount_slave);
mount_slave_mounted = false;
(void) rmdir(mount_slave);
mount_slave_created = false;
child = fork();
if (child < 0) {
r = log_error_errno(errno, "Failed to fork(): %m");
goto finish;
}
if (child == 0) {
const char *mount_inside;
int mntfd;
const char *q;
q = procfs_file_alloca(leader, "ns/mnt");
mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (mntfd < 0) {
log_error_errno(errno, "Failed to open mount namespace of leader: %m");
_exit(EXIT_FAILURE);
}
if (setns(mntfd, CLONE_NEWNS) < 0) {
log_error_errno(errno, "Failed to join namespace of leader: %m");
_exit(EXIT_FAILURE);
}
if (arg_mkdir)
mkdir_p(dest, 0755);
/* Fifth, move the mount to the right place inside */
mount_inside = strappenda("/run/systemd/nspawn/incoming/", basename(mount_outside));
if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
log_error_errno(errno, "Failed to mount: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(child, &si);
if (r < 0) {
log_error_errno(r, "Failed to wait for client: %m");
goto finish;
}
if (si.si_code != CLD_EXITED) {
log_error("Client died abnormally.");
r = -EIO;
goto finish;
}
if (si.si_status != EXIT_SUCCESS) {
r = -EIO;
goto finish;
}
r = 0;
finish:
if (mount_outside_mounted)
umount(mount_outside);
if (mount_outside_created)
rmdir(mount_outside);
if (mount_tmp_mounted)
umount(mount_tmp);
if (mount_tmp_created)
umount(mount_tmp);
if (mount_slave_mounted)
umount(mount_slave);
if (mount_slave_created)
umount(mount_slave);
return r;
}
static int on_machine_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
PTYForward ** forward = (PTYForward**) userdata;
int r;
assert(bus);
assert(m);
assert(forward);
if (*forward) {
/* If the forwarder is already initialized, tell it to
* exit on the next vhangup(), so that we still flush
* out what might be queued and exit then. */
r = pty_forward_set_ignore_vhangup(*forward, false);
if (r >= 0)
return 0;
log_error_errno(r, "Failed to set ignore_vhangup flag: %m");
}
/* On error, or when the forwarder is not initialized yet, quit immediately */
sd_event_exit(sd_bus_get_event(bus), EXIT_FAILURE);
return 0;
}
static int login_machine(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
_cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
_cleanup_event_unref_ sd_event *event = NULL;
int master = -1, r, ret = 0;
sd_bus *bus = userdata;
const char *pty, *match;
sigset_t mask;
char last_char = 0;
bool machine_died;
assert(bus);
if (arg_transport != BUS_TRANSPORT_LOCAL &&
arg_transport != BUS_TRANSPORT_MACHINE) {
log_error("Login only supported on local machines.");
return -ENOTSUP;
}
polkit_agent_open_if_enabled();
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to get event loop: %m");
r = sd_bus_attach_event(bus, event, 0);
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
match = strappenda("type='signal',"
"sender='org.freedesktop.machine1',"
"path='/org/freedesktop/machine1',",
"interface='org.freedesktop.machine1.Manager',"
"member='MachineRemoved',"
"arg0='",
argv[1],
"'");
r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward);
if (r < 0)
return log_error_errno(r, "Failed to add machine removal match: %m");
r = sd_bus_message_new_method_call(bus,
&m,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"OpenMachineLogin");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "s", argv[1]);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "hs", &master, &pty);
if (r < 0)
return bus_log_parse_error(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 machine %s. Press ^] three times within 1s to exit session.", argv[1]);
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
r = pty_forward_new(event, master, true, &forward);
if (r < 0)
return log_error_errno(r, "Failed to create PTY forwarder: %m");
r = sd_event_loop(event);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
pty_forward_get_last_char(forward, &last_char);
machine_died = pty_forward_get_ignore_vhangup(forward) == 0;
forward = pty_forward_free(forward);
if (last_char != '\n')
fputc('\n', stdout);
if (machine_died)
log_info("Machine %s terminated.", argv[1]);
else
log_info("Connection to machine %s terminated.", argv[1]);
sd_event_get_exit_code(event, &ret);
return ret;
}
static int remove_image(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
for (i = 1; i < argc; i++) {
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"RemoveImage",
&error,
NULL,
"s", argv[i]);
if (r < 0) {
log_error("Could not remove image: %s", bus_error_message(&error, -r));
return r;
}
}
return 0;
}
static int rename_image(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
polkit_agent_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"RenameImage",
&error,
NULL,
"ss", argv[1], argv[2]);
if (r < 0) {
log_error("Could not rename image: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int clone_image(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
polkit_agent_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"CloneImage",
&error,
NULL,
"ssb", argv[1], argv[2], arg_read_only);
if (r < 0) {
log_error("Could not clone image: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int read_only_image(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int b = true, r;
if (argc > 2) {
b = parse_boolean(argv[2]);
if (b < 0) {
log_error("Failed to parse boolean argument: %s", argv[2]);
return -EINVAL;
}
}
polkit_agent_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"MarkImageReadOnly",
&error,
NULL,
"sb", argv[1], b);
if (r < 0) {
log_error("Could not mark image read-only: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int start_machine(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_oom();
for (i = 1; i < argc; i++) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
_cleanup_free_ char *e = NULL, *unit = NULL;
const char *object;
if (!machine_name_is_valid(argv[i])) {
log_error("Invalid machine name %s.", argv[i]);
return -EINVAL;
}
e = unit_name_escape(argv[i]);
if (!e)
return log_oom();
unit = unit_name_build("systemd-nspawn", e, ".service");
if (!unit)
return log_oom();
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "ss", unit, "fail");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed to start unit: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "o", &object);
if (r < 0)
return bus_log_parse_error(r);
r = bus_wait_for_jobs_add(w, object);
if (r < 0)
return log_oom();
}
r = bus_wait_for_jobs(w, arg_quiet);
if (r < 0)
return r;
return 0;
}
static int enable_machine(int argc, char *argv[], void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int carries_install_info = 0;
const char *method = NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles";
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
method);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
for (i = 1; i < argc; i++) {
_cleanup_free_ char *e = NULL, *unit = NULL;
if (!machine_name_is_valid(argv[i])) {
log_error("Invalid machine name %s.", argv[i]);
return -EINVAL;
}
e = unit_name_escape(argv[i]);
if (!e)
return log_oom();
unit = unit_name_build("systemd-nspawn", e, ".service");
if (!unit)
return log_oom();
r = sd_bus_message_append(m, "s", unit);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
if (streq(argv[0], "enable"))
r = sd_bus_message_append(m, "bb", false, false);
else
r = sd_bus_message_append(m, "b", false);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed to enable or disable unit: %s", bus_error_message(&error, -r));
return r;
}
if (streq(argv[0], "enable")) {
r = sd_bus_message_read(reply, "b", carries_install_info);
if (r < 0)
return bus_log_parse_error(r);
}
r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
if (r < 0)
return r;
m = sd_bus_message_unref(m);
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"Reload");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, NULL);
if (r < 0) {
log_error("Failed to reload daemon: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int help(int argc, char *argv[], void *userdata) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the virtual machine and container\n"
"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-legend Do not show the headers and footers\n"
" --no-ask-password Do not ask for system passwords\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"
" -q --quiet Suppress output\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"
" --read-only Create read-only bind mount\n"
" --mkdir Create directory before bind mounting, if missing\n"
" -n --lines=INTEGER Number of journal entries to show\n"
" -o --output=STRING Change journal output mode (short,\n"
" short-monotonic, verbose, export, json,\n"
" json-pretty, json-sse, cat)\n\n"
"Machine Commands:\n"
" list List running VMs and containers\n"
" status NAME... Show VM/container details\n"
" show NAME... Show properties of one or more VMs/containers\n"
" start NAME... Start container as a service\n"
" login NAME Get a login prompt on a container\n"
" enable NAME... Enable automatic container start at boot\n"
" disable NAME... Disable automatic container start at boot\n"
" poweroff NAME... Power off one or more containers\n"
" reboot NAME... Reboot one or more containers\n"
" terminate NAME... Terminate one or more VMs/containers\n"
" kill NAME... Send signal to processes of a VM/container\n"
" copy-to NAME PATH [PATH] Copy files from the host to a container\n"
" copy-from NAME PATH [PATH] Copy files from a container to the host\n"
" bind NAME PATH [PATH] Bind mount a path from the host into a container\n\n"
"Image Commands:\n"
" list-images Show available images\n"
" image-status NAME... Show image details\n"
" show-image NAME... Show properties of image\n"
" clone NAME NAME Clone an image\n"
" rename NAME NAME Rename an image\n"
" read-only NAME [BOOL] Mark or unmark image read-only\n"
" remove NAME... Remove an image\n"
, program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_NO_LEGEND,
ARG_KILL_WHO,
ARG_READ_ONLY,
ARG_MKDIR,
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 },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
{ "signal", required_argument, NULL, 's' },
{ "host", required_argument, NULL, 'H' },
{ "machine", required_argument, NULL, 'M' },
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
{ "mkdir", no_argument, NULL, ARG_MKDIR },
{ "quiet", no_argument, NULL, 'q' },
{ "lines", required_argument, NULL, 'n' },
{ "output", required_argument, NULL, 'o' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{}
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hp:als:H:M:qn:o:", options, NULL)) >= 0)
switch (c) {
case 'h':
return help(0, NULL, NULL);
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 'n':
if (safe_atou(optarg, &arg_lines) < 0) {
log_error("Failed to parse lines '%s'", optarg);
return -EINVAL;
}
break;
case 'o':
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
return -EINVAL;
}
break;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case ARG_NO_LEGEND:
arg_legend = 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 ARG_NO_ASK_PASSWORD:
arg_ask_password = false;
break;
case 'H':
arg_transport = BUS_TRANSPORT_REMOTE;
arg_host = optarg;
break;
case 'M':
arg_transport = BUS_TRANSPORT_MACHINE;
arg_host = optarg;
break;
case ARG_READ_ONLY:
arg_read_only = true;
break;
case ARG_MKDIR:
arg_mkdir = true;
break;
case 'q':
arg_quiet = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
return 1;
}
static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "list", VERB_ANY, 1, VERB_DEFAULT, list_machines },
{ "list-images", VERB_ANY, 1, 0, list_images },
{ "status", 2, VERB_ANY, 0, show_machine },
{ "image-status",2, VERB_ANY, 0, show_image },
{ "show", VERB_ANY, VERB_ANY, 0, show_machine },
{ "show-image", VERB_ANY, VERB_ANY, 0, show_image },
{ "terminate", 2, VERB_ANY, 0, terminate_machine },
{ "reboot", 2, VERB_ANY, 0, reboot_machine },
{ "poweroff", 2, VERB_ANY, 0, poweroff_machine },
{ "kill", 2, VERB_ANY, 0, kill_machine },
{ "login", 2, 2, 0, login_machine },
{ "bind", 3, 4, 0, bind_mount },
{ "copy-to", 3, 4, 0, copy_files },
{ "copy-from", 3, 4, 0, copy_files },
{ "remove", 2, VERB_ANY, 0, remove_image },
{ "rename", 3, 3, 0, rename_image },
{ "clone", 3, 3, 0, clone_image },
{ "read-only", 2, 3, 0, read_only_image },
{ "start", 2, VERB_ANY, 0, start_machine },
{ "enable", 2, VERB_ANY, 0, enable_machine },
{ "disable", 2, VERB_ANY, 0, enable_machine },
{}
};
return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char*argv[]) {
_cleanup_bus_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = bus_open_transport(arg_transport, arg_host, false, &bus);
if (r < 0) {
log_error_errno(r, "Failed to create bus connection: %m");
goto finish;
}
r = machinectl_main(argc, argv, bus);
finish:
pager_close();
polkit_agent_close();
strv_free(arg_property);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}