machinectl.c revision 56b921c3d863f0e098f60f934e6c5880575c68ab
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"
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart 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"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "path-util.h"
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen#include "mkdir.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "copy.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "verbs.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "import-util.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 Poetteringstatic bool arg_force = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char* arg_dkr_index_url = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic void pager_open_if_enabled(void) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen 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 */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!arg_ask_password)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen if (arg_transport != BUS_TRANSPORT_LOCAL)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen polkit_agent_open();
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic OutputFlags get_output_flags(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_all * OUTPUT_SHOW_ALL |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_full * OUTPUT_FULL_WIDTH |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen on_tty() * OUTPUT_COLOR |
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering !arg_quiet * OUTPUT_WARN_CUTOFF;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersentypedef struct MachineInfo {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering const char *name;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *class;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen const char *service;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen} MachineInfo;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int compare_machine_info(const void *a, const void *b) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const MachineInfo *x = a, *y = b;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return strcmp(x->name, y->name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering 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;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering sd_bus *bus = userdata;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(bus);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering pager_open_if_enabled();
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = sd_bus_call_method(
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bus,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.machine1",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "/org/freedesktop/machine1",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering "org.freedesktop.machine1.Manager",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering "ListMachines",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering &error,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen &reply,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering NULL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Could not get machines: %s", bus_error_message(&error, -r));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering if (r < 0)
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return bus_log_parse_error(r);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering size_t l;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1))
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return log_oom();
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering machines[n_machines].name = name;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering machines[n_machines].class = class;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart 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)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering max_class = l;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering l = strlen(service);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (l > max_service)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering max_service = l;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering n_machines ++;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart 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++)
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering printf("%-*s %-*s %-*s\n",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_name, machines[j].name,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_class, machines[j].class,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_service, machines[j].service);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (arg_legend)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering printf("\n%zu machines listed.\n", n_machines);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return 0;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringtypedef struct ImageInfo {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const char *name;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const char *type;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering bool read_only;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering usec_t crtime;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering usec_t mtime;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering uint64_t size;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering} ImageInfo;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering const ImageInfo *x = a, *y = b;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return strcmp(x->name, y->name);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart 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("USAGE"), 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();
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_call_method(
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart 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)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_type = l;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (crtime != 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (l > max_crtime)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering max_crtime = l;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (mtime != 0) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (l > max_mtime)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_mtime = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (size != (uint64_t) -1) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (l > max_size)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering max_size = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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, "USAGE",
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;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering _cleanup_free_ char *path = NULL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart 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,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering "s");
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = sd_bus_message_read(reply, "s", &cgroup);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (isempty(cgroup))
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart 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;
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
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);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(prefix);
a6c616024db23fef34152c1432892824a07799ccLennart Poettering assert(prefix2);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = sd_bus_call_method(bus,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "org.freedesktop.machine1",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "/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)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a6c616024db23fef34152c1432892824a07799ccLennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iay)");
a6c616024db23fef34152c1432892824a07799ccLennart Poettering if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int family;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const void *a;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers size_t sz;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_read(reply, "i", &family);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_read_array(reply, 'y', &a, &sz);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(prefix, stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (family == AF_INET6 && ifi > 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers printf("%%%i", ifi);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputc('\n', stdout);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_exit_container(reply);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (prefix != prefix2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering prefix = prefix2;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers 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}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peetersstatic int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers const char *k, *v, *pretty = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(prefix);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_call_method(bus,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/machine1",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "org.freedesktop.machine1.Manager",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "GetMachineOSRelease",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering NULL,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "s", name);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "{ss}");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (streq(k, "PRETTY_NAME"))
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni pretty = v;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
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);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
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;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering char *root_directory;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering pid_t leader;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct dual_timestamp timestamp;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers int *netif;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned n_netif;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers} MachineStatusInfo;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char since2[FORMAT_TIMESTAMP_MAX], *s2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int ifi = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(bus);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(strna(i->name), stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
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);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (s1)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen 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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering get_process_comm(i->leader, &t);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (t)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf(" (%s)", t);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering putchar('\n');
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (i->service) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering printf("\t Service: %s", i->service);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i->root_directory)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering printf("\t Root: %s\n", i->root_directory);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i->n_netif > 0) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering unsigned c;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering fputs("\t Iface:", stdout);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering for (c = 0; c < i->n_netif; c++) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering char name[IF_NAMESIZE+1] = "";
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (if_indextoname(i->netif[c], name)) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering fputc(' ', stdout);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering fputs(name, stdout);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (ifi < 0)
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering ifi = i->netif[c];
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering else
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering ifi = 0;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering } else
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering printf(" %i", i->netif[c]);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering fputc('\n', stdout);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart 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: ");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
3d94f76c99da13e5603831d0b278f8c8c21bcb02Lennart Poettering if (i->unit) {
a4475f577bd0daf762d6c3b4e58bc484e0cb74afLennart Poettering printf("\t Unit: %s\n", i->unit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering show_unit_cgroup(bus, i->unit, i->leader);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (arg_transport == BUS_TRANSPORT_LOCAL) {
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek show_journal_by_unit(
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek stdout,
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek i->unit,
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek arg_output,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 0,
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen i->timestamp.monotonic,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering arg_lines,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 0,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering get_output_flags() | OUTPUT_BEGIN_NEWLINE,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering SD_JOURNAL_LOCAL_ONLY,
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering true,
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart 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;
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_cc(sizeof(int32_t) == sizeof(int));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart 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
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering static const struct bus_properties_map map[] = {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp.realtime) },
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering { "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) },
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering { "NetworkInterfaces", "ai", map_netif, 0 },
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering {}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering };
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering MachineStatusInfo info = {};
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart 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;
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering print_machine_status_info(bus, &info);
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.name);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.class);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.service);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.unit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.root_directory);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.netif);
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering return r;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart 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);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(path);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*new_line)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\n");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering *new_line = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering log_error_errno(r, "Could not get properties: %m");
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering return r;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering}
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poetteringstatic int show_machine(int argc, char *argv[], void *userdata) {
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering bool properties, new_line = false;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering sd_bus *bus = userdata;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering int r = 0, i;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering properties = !strstr(argv[0], "status");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart 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 }
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart 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",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "/org/freedesktop/machine1",
04d39279245834494baccfdb9349db8bf80abd13Lennart 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
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering r = sd_bus_message_read(reply, "o", &path);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart 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
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 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 usage;
3db729cb8e6822114e9323f4041dcdc080f2fb3cJason A. Donenfeld uint64_t limit;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering uint64_t usage_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);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering putchar('\n');
04d39279245834494baccfdb9349db8bf80abd13Lennart 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() : "",
a6c616024db23fef34152c1432892824a07799ccLennart Poettering i->read_only ? "read-only" : "writable",
a6c616024db23fef34152c1432892824a07799ccLennart 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)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering printf("\t Created: %s\n", s2);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->mtime);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->mtime);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (s1 && s2)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering printf("\tModified: %s; %s\n", s2, s1);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering else if (s2)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering printf("\tModified: %s\n", s2);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering s3 = format_bytes(bs, sizeof(bs), i->usage);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s4 = i->usage_exclusive != i->usage ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->usage_exclusive) : NULL;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (s3 && s4)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Usage: %s (exclusive: %s)\n", s3, s4);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (s3)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Usage: %s\n", s3);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering s3 = format_bytes(bs, sizeof(bs), i->limit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s3 && s4)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Limit: %s (exclusive: %s)\n", s3, s4);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (s3)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering printf("\t Limit: %s\n", s3);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int show_image_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek
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) },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) },
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) },
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) },
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering { "Usage", "t", NULL, offsetof(ImageStatusInfo, usage) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "UsageExclusive", "t", NULL, offsetof(ImageStatusInfo, usage_exclusive) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering {}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ImageStatusInfo info = {};
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek int r;
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering assert(verb);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering assert(bus);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering assert(path);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering assert(new_line);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_map_all_properties(bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering path,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering map,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen if (*new_line)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *new_line = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering print_image_status_info(bus, &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_image_properties(sd_bus *bus, const char *path, bool *new_line) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(new_line);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*new_line)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *new_line = true;
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek
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
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek return r;
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek}
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;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering sd_bus *bus = userdata;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering int r = 0, i;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *path = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bus,
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen "org.freedesktop.machine1",
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen "/org/freedesktop/machine1",
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen "org.freedesktop.machine1.Manager",
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen "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));
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (properties)
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering r = show_image_properties(bus, path, &new_line);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering else
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = show_image_info(argv[0], bus, path, &new_line);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering return r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int kill_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
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering polkit_agent_open_if_enabled();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!arg_kill_who)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_kill_who = "all";
04d39279245834494baccfdb9349db8bf80abd13Lennart 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",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart 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";
46e65dcc3a522b5e992e165b5e61d14254026859Lennart 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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ret);
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 "GetMachine",
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering &error,
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering &reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "s", name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering r = sd_bus_message_read(reply, "o", &object);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_get_property(
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering bus,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen object,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1.Machine",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "Leader",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply2,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "u");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering return log_error_errno(r, "Failed to retrieve PID of leader: %m");
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering r = sd_bus_message_read(reply2, "u", &leader);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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 = strdupa(host_path);
host_basename = basename(t);
host_dirname = dirname(host_path);
t = strdupa(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;
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);
sigprocmask_many(SIG_BLOCK, SIGWINCH, SIGTERM, SIGINT, -1);
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 match_log_message(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
const char **our_path = userdata, *line;
unsigned priority;
int r;
assert(bus);
assert(m);
assert(our_path);
r = sd_bus_message_read(m, "us", &priority, &line);
if (r < 0) {
bus_log_parse_error(r);
return 0;
}
if (!streq_ptr(*our_path, sd_bus_message_get_path(m)))
return 0;
if (arg_quiet && LOG_PRI(priority) >= LOG_INFO)
return 0;
log_full(priority, "%s", line);
return 0;
}
static int match_transfer_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
const char **our_path = userdata, *path, *result;
uint32_t id;
int r;
assert(bus);
assert(m);
assert(our_path);
r = sd_bus_message_read(m, "uos", &id, &path, &result);
if (r < 0) {
bus_log_parse_error(r);
return 0;
}
if (!streq_ptr(*our_path, path))
return 0;
sd_event_exit(sd_bus_get_event(bus), !streq_ptr(result, "done"));
return 0;
}
static int transfer_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
assert(si);
if (!arg_quiet)
log_info("Continuing download in the background. Use \"machinectl cancel-transfer %" PRIu32 "\" to arbort transfer.", PTR_TO_UINT32(userdata));
sd_event_exit(sd_event_source_get_event(s), EINTR);
return 0;
}
static int pull_image_common(sd_bus *bus, sd_bus_message *m) {
_cleanup_bus_slot_unref_ sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_event_unref_ sd_event* event = NULL;
const char *path = NULL;
uint32_t id;
int r;
assert(bus);
assert(m);
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");
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_add_match(
bus,
&slot_job_removed,
"type='signal',"
"sender='org.freedesktop.import1',"
"interface='org.freedesktop.import1.Manager',"
"member='TransferRemoved',"
"path='/org/freedesktop/import1'",
match_transfer_removed, &path);
if (r < 0)
return log_error_errno(r, "Failed to install match: %m");
r = sd_bus_add_match(
bus,
&slot_log_message,
"type='signal',"
"sender='org.freedesktop.import1',"
"interface='org.freedesktop.import1.Transfer',"
"member='LogMessage'",
match_log_message, &path);
if (r < 0)
return log_error_errno(r, "Failed to install match: %m");
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed pull image: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "uo", &id, &path);
if (r < 0)
return bus_log_parse_error(r);
sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1);
if (!arg_quiet)
log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id);
sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id));
sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id));
r = sd_event_loop(event);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
return -r;
}
static int pull_tar(int argc, char *argv[], void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *l = NULL, *ll = NULL;
const char *local, *remote;
sd_bus *bus = userdata;
int r;
assert(bus);
remote = argv[1];
if (!http_url_is_valid(remote)) {
log_error("URL '%s' is not valid.", remote);
return -EINVAL;
}
if (argc >= 3)
local = argv[2];
else {
r = import_url_last_component(remote, &l);
if (r < 0)
return log_error_errno(r, "Failed to get final component of URL: %m");
local = l;
}
if (isempty(local) || streq(local, "-"))
local = NULL;
if (local) {
r = tar_strip_suffixes(local, &ll);
if (r < 0)
return log_error_errno(r, "Failed to strip tar suffixes: %m");
local = ll;
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"PullTar");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"sssb",
remote,
local,
import_verify_to_string(arg_verify),
arg_force);
if (r < 0)
return bus_log_create_error(r);
return pull_image_common(bus, m);
}
static int pull_raw(int argc, char *argv[], void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *l = NULL, *ll = NULL;
const char *local, *remote;
sd_bus *bus = userdata;
int r;
assert(bus);
remote = argv[1];
if (!http_url_is_valid(remote)) {
log_error("URL '%s' is not valid.", remote);
return -EINVAL;
}
if (argc >= 3)
local = argv[2];
else {
r = import_url_last_component(remote, &l);
if (r < 0)
return log_error_errno(r, "Failed to get final component of URL: %m");
local = l;
}
if (isempty(local) || streq(local, "-"))
local = NULL;
if (local) {
r = raw_strip_suffixes(local, &ll);
if (r < 0)
return log_error_errno(r, "Failed to strip tar suffixes: %m");
local = ll;
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"PullRaw");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"sssb",
remote,
local,
import_verify_to_string(arg_verify),
arg_force);
if (r < 0)
return bus_log_create_error(r);
return pull_image_common(bus, m);
}
static int pull_dkr(int argc, char *argv[], void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *l = NULL, *ll = NULL;
const char *local, *remote, *tag;
sd_bus *bus = userdata;
int r;
if (arg_verify != IMPORT_VERIFY_NO) {
log_error("Imports from DKR do not support image verification, please pass --verify=no.");
return -EINVAL;
}
remote = argv[1];
tag = strchr(remote, ':');
if (tag) {
remote = strndupa(remote, tag - remote);
tag++;
}
if (!dkr_name_is_valid(remote)) {
log_error("DKR name '%s' is invalid.", remote);
return -EINVAL;
}
if (tag && !dkr_tag_is_valid(tag)) {
log_error("DKR tag '%s' is invalid.", remote);
return -EINVAL;
}
if (argc >= 3)
local = argv[2];
else {
local = strchr(remote, '/');
if (local)
local++;
else
local = remote;
}
if (isempty(local) || streq(local, "-"))
local = NULL;
if (local) {
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"PullDkr");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"sssssb",
arg_dkr_index_url,
remote,
tag,
local,
import_verify_to_string(arg_verify),
arg_force);
if (r < 0)
return bus_log_create_error(r);
return pull_image_common(bus, m);
}
typedef struct TransferInfo {
uint32_t id;
const char *type;
const char *remote;
const char *local;
double progress;
} TransferInfo;
static int compare_transfer_info(const void *a, const void *b) {
const TransferInfo *x = a, *y = b;
return strcmp(x->local, y->local);
}
static int list_transfers(int argc, char *argv[], void *userdata) {
size_t max_type = strlen("TYPE"), max_local = strlen("LOCAL"), max_remote = strlen("REMOTE");
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ TransferInfo *transfers = NULL;
size_t n_transfers = 0, n_allocated = 0, j;
const char *type, *remote, *local, *object;
sd_bus *bus = userdata;
uint32_t id, max_id = 0;
double progress;
int r;
pager_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"ListTransfers",
&error,
&reply,
NULL);
if (r < 0) {
log_error("Could not get transfers: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_enter_container(reply, 'a', "(usssdo)");
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, &object)) > 0) {
size_t l;
if (!GREEDY_REALLOC(transfers, n_allocated, n_transfers + 1))
return log_oom();
transfers[n_transfers].id = id;
transfers[n_transfers].type = type;
transfers[n_transfers].remote = remote;
transfers[n_transfers].local = local;
transfers[n_transfers].progress = progress;
l = strlen(type);
if (l > max_type)
max_type = l;
l = strlen(remote);
if (l > max_remote)
max_remote = l;
l = strlen(local);
if (l > max_local)
max_local = l;
if (id > max_id)
max_id = id;
n_transfers ++;
}
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
qsort_safe(transfers, n_transfers, sizeof(TransferInfo), compare_transfer_info);
if (arg_legend)
printf("%-*s %-*s %-*s %-*s %-*s\n",
(int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), "ID",
(int) 7, "PERCENT",
(int) max_type, "TYPE",
(int) max_local, "LOCAL",
(int) max_remote, "REMOTE");
for (j = 0; j < n_transfers; j++)
printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n",
(int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
(int) 6, (unsigned) (transfers[j].progress * 100),
(int) max_type, transfers[j].type,
(int) max_local, transfers[j].local,
(int) max_remote, transfers[j].remote);
if (arg_legend)
printf("\n%zu transfers listed.\n", n_transfers);
return 0;
}
static int cancel_transfer(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++) {
uint32_t id;
r = safe_atou32(argv[i], &id);
if (r < 0)
return log_error_errno(r, "Failed to parse transfer id: %s", argv[i]);
r = sd_bus_call_method(
bus,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"CancelTransfer",
&error,
NULL,
"u", id);
if (r < 0) {
log_error("Could not cancel transfer: %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"
" --verify=MODE Verification mode for downloaded images (no,\n"
" checksum, signature)\n"
" --force Download image even if already exists\n"
" --dkr-index-url=URL Specify the index URL to use for DKR image\n"
" downloads\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 container and VM 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\n"
"Image Transfer Commands:\n"
" pull-tar URL [NAME] Download a TAR container image\n"
" pull-raw URL [NAME] Download a RAW container or VM image\n"
" pull-dkr REMOTE [NAME] Download a DKR container image\n"
" list-transfers Show list of downloads in progress\n"
" cancel-transfer Cancel a download\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,
ARG_VERIFY,
ARG_FORCE,
ARG_DKR_INDEX_URL,
};
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 },
{ "verify", required_argument, NULL, ARG_VERIFY },
{ "force", no_argument, NULL, ARG_FORCE },
{ "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
{}
};
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 ARG_VERIFY:
arg_verify = import_verify_from_string(optarg);
if (arg_verify < 0) {
log_error("Failed to parse --verify= setting: %s", optarg);
return -EINVAL;
}
break;
case ARG_FORCE:
arg_force = true;
break;
case ARG_DKR_INDEX_URL:
if (!http_url_is_valid(optarg)) {
log_error("Index URL is invalid: %s", optarg);
return -EINVAL;
}
arg_dkr_index_url = optarg;
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 },
{ "pull-tar", 2, 3, 0, pull_tar },
{ "pull-raw", 2, 3, 0, pull_raw },
{ "pull-dkr", 2, 3, 0, pull_dkr },
{ "list-transfers", VERB_ANY, 1, 0, list_transfers },
{ "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer },
{}
};
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;
}