X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fmachine%2Fmachinectl.c;h=04c7c7c670213282258b207303de50274576f667;hb=ea30eb86e5a370fb8cb94e352e075e24d940d159;hp=d812ef2600dcd08e30f344f1c5f5b17c6258336a;hpb=03e334a1c7dc8c20c38902aa039440763acc9b17;p=elogind.git diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index d812ef260..04c7c7c67 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include "sd-bus.h" #include "log.h" @@ -165,6 +168,109 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { return 0; } +static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) { + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + int r; + + assert(bus); + assert(name); + assert(prefix); + assert(prefix2); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineAddresses", + NULL, + &reply, + "s", name); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'a', "(yay)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_enter_container(reply, 'r', "yay")) > 0) { + unsigned char family; + const void *a; + size_t sz; + char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)]; + + r = sd_bus_message_read(reply, "y", &family); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + return bus_log_parse_error(r); + + fputs(prefix, stdout); + fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout); + if (family == AF_INET6 && ifi > 0) + printf("%%%i", ifi); + fputc('\n', stdout); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (prefix != prefix2) + prefix = prefix2; + } + 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); + + return 0; +} + +static int print_os_release(sd_bus *bus, const char *name, const char *prefix) { + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + const char *k, *v, *pretty = NULL; + int r; + + assert(bus); + assert(name); + assert(prefix); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineOSRelease", + NULL, + &reply, + "s", name); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'a', "{ss}"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { + if (streq(k, "PRETTY_NAME")) + pretty = v; + + } + 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); + + if (pretty) + printf("%s%s\n", prefix, pretty); + + return 0; +} + typedef struct MachineStatusInfo { char *name; sd_id128_t id; @@ -174,11 +280,15 @@ typedef struct MachineStatusInfo { char *root_directory; pid_t leader; usec_t timestamp; + int *netif; + unsigned n_netif; } MachineStatusInfo; static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; + int ifi = -1; + assert(i); fputs(strna(i->name), stdout); @@ -221,23 +331,72 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { if (i->root_directory) printf("\t Root: %s\n", i->root_directory); + if (i->n_netif > 0) { + unsigned c; + + fputs("\t Iface:", stdout); + + for (c = 0; c < i->n_netif; c++) { + char name[IF_NAMESIZE+1] = ""; + + if (if_indextoname(i->netif[c], name)) { + fputc(' ', stdout); + fputs(name, stdout); + + if (ifi < 0) + ifi = i->netif[c]; + else + ifi = 0; + } else + printf(" %i", i->netif[c]); + } + + fputc('\n', stdout); + } + + print_addresses(bus, i->name, ifi, + "\t Address: ", + "\t "); + + print_os_release(bus, i->name, "\t OS: "); + if (i->unit) { printf("\t Unit: %s\n", i->unit); show_unit_cgroup(bus, i->unit, i->leader); } } +static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + MachineStatusInfo *i = userdata; + size_t l; + const void *v; + int r; + + assert_cc(sizeof(int32_t) == sizeof(int)); + r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l); + if (r < 0) + return r; + + i->n_netif = l / sizeof(int32_t); + i->netif = memdup(v, l); + if (!i->netif) + return -ENOMEM; + + return 0; +} + static int show_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) { static const struct bus_properties_map map[] = { - { "Name", "s", NULL, offsetof(MachineStatusInfo, name) }, - { "Class", "s", NULL, offsetof(MachineStatusInfo, class) }, - { "Service", "s", NULL, offsetof(MachineStatusInfo, service) }, - { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) }, - { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) }, - { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) }, - { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp) }, - { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) }, + { "Name", "s", NULL, offsetof(MachineStatusInfo, name) }, + { "Class", "s", NULL, offsetof(MachineStatusInfo, class) }, + { "Service", "s", NULL, offsetof(MachineStatusInfo, service) }, + { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) }, + { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) }, + { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) }, + { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp) }, + { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) }, + { "NetworkInterfaces", "ai", map_netif, 0 }, {} }; @@ -268,6 +427,7 @@ static int show_info(const char *verb, sd_bus *bus, const char *path, bool *new_ free(info.service); free(info.unit); free(info.root_directory); + free(info.netif); return r; } @@ -412,7 +572,7 @@ static int terminate_machine(sd_bus *bus, char **args, unsigned n) { } static int openpt_in_namespace(pid_t pid, int flags) { - _cleanup_close_pipe_ int pair[2] = { -1, -1 }; + _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1; union { struct cmsghdr cmsghdr; @@ -427,7 +587,7 @@ static int openpt_in_namespace(pid_t pid, int flags) { pid_t child; siginfo_t si; - r = namespace_open(pid, &pidnsfd, &mntnsfd, &rootfd); + r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd); if (r < 0) return r; @@ -441,7 +601,7 @@ static int openpt_in_namespace(pid_t pid, int flags) { if (child == 0) { pair[0] = safe_close(pair[0]); - r = namespace_enter(pidnsfd, mntnsfd, rootfd); + r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd); if (r < 0) _exit(EXIT_FAILURE); @@ -466,10 +626,10 @@ static int openpt_in_namespace(pid_t pid, int flags) { pair[1] = safe_close(pair[1]); r = wait_for_terminate(child, &si); - if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) { - - return r < 0 ? r : -EIO; - } + if (r < 0) + return r; + if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) + return -EIO; if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0) return -errno;