X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcgls%2Fcgls.c;h=052ac8ffca3395943fa18f79f80252478cf08149;hp=b2cd968e46cfeeae5b39f347db7b50739235ff82;hb=bce415edcae8e7af8327de8265d621f95fa5426f;hpb=9eb977db5b89b44f254ab40c1876a76b7d7ea2d0;ds=sidebyside diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index b2cd968e4..052ac8ffc 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -33,12 +33,20 @@ #include "util.h" #include "pager.h" #include "build.h" +#include "output-mode.h" +#include "fileio.h" +#include "sd-bus.h" +#include "bus-util.h" +#include "bus-error.h" +#include "unit-name.h" static bool arg_no_pager = false; static bool arg_kernel_threads = false; static bool arg_all = false; +static int arg_full = -1; +static char* arg_machine = NULL; -static void help(void) { +static int help(void) { printf("%s [OPTIONS...] [CGROUP...]\n\n" "Recursively show control group contents.\n\n" @@ -46,15 +54,19 @@ static void help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all groups, including empty\n" - " -k Include kernel threads in output\n", + " -l --full Do not ellipsize output\n" + " -k Include kernel threads in output\n" + " -M --machine Show container\n", program_invocation_short_name); + + return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_NO_PAGER = 0x100, - ARG_VERSION + ARG_VERSION, }; static const struct option options[] = { @@ -62,7 +74,9 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "all", no_argument, NULL, 'a' }, - { NULL, 0, NULL, 0 } + { "full", no_argument, NULL, 'l' }, + { "machine", required_argument, NULL, 'M' }, + {} }; int c; @@ -70,17 +84,15 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 1); assert(argv); - while ((c = getopt_long(argc, argv, "hka", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0) { switch (c) { case 'h': - help(); - return 0; + return help(); case ARG_VERSION: puts(PACKAGE_STRING); - puts(DISTRIBUTION); puts(SYSTEMD_FEATURES); return 0; @@ -92,16 +104,23 @@ static int parse_argv(int argc, char *argv[]) { arg_all = true; break; + case 'l': + arg_full = true; + break; + case 'k': arg_kernel_threads = true; break; + case 'M': + arg_machine = optarg; + break; + case '?': return -EINVAL; default: - log_error("Unknown option code %c", c); - return -EINVAL; + assert_not_reached("Unhandled option"); } } @@ -110,6 +129,9 @@ static int parse_argv(int argc, char *argv[]) { int main(int argc, char *argv[]) { int r = 0, retval = EXIT_FAILURE; + int output_flags; + _cleanup_free_ char *root = NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; log_parse_environment(); log_open(); @@ -122,23 +144,48 @@ int main(int argc, char *argv[]) { goto finish; } - if (!arg_no_pager) - pager_open(); + if (!arg_no_pager) { + r = pager_open(false); + if (r > 0) { + if (arg_full == -1) + arg_full = true; + } + } + + output_flags = + arg_all * OUTPUT_SHOW_ALL | + (arg_full > 0) * OUTPUT_FULL_WIDTH; + + r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) { + log_error("Failed to create bus connection: %s", strerror(-r)); + goto finish; + } if (optind < argc) { - unsigned i; + int i; - for (i = (unsigned) optind; i < (unsigned) argc; i++) { + for (i = optind; i < argc; i++) { int q; - printf("%s:\n", argv[i]); - q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, arg_all); + fprintf(stdout, "%s:\n", argv[i]); + fflush(stdout); + + if (arg_machine) + root = strjoin("machine/", arg_machine, "/", argv[i], NULL); + else + root = strdup(argv[i]); + if (!root) + return log_oom(); + + q = show_cgroup_by_path(root, NULL, 0, + arg_kernel_threads, output_flags); if (q < 0) r = q; } } else { - char *p; + _cleanup_free_ char *p; p = get_current_dir_name(); if (!p) { @@ -146,34 +193,77 @@ int main(int argc, char *argv[]) { goto finish; } - if (path_startswith(p, "/sys/fs/cgroup")) { + if (path_startswith(p, "/sys/fs/cgroup") && !arg_machine) { printf("Working Directory %s:\n", p); - r = show_cgroup_by_path(p, NULL, 0, arg_kernel_threads, arg_all); + r = show_cgroup_by_path(p, NULL, 0, + arg_kernel_threads, output_flags); } else { - char *root = NULL; - const char *t = NULL; - - r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root); - if (r < 0) - t = "/"; - else { - if (endswith(root, "/system")) - root[strlen(root)-7] = 0; - - t = root[0] ? root : "/"; + if (arg_machine) { + char *m; + const char *cgroup; + _cleanup_free_ char *scope = NULL; + _cleanup_free_ char *path = NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + + m = strappenda("/run/systemd/machines/", arg_machine); + r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL); + if (r < 0) { + log_error("Failed to get machine path: %s", strerror(-r)); + goto finish; + } + + path = unit_dbus_path_from_name(scope); + if (!path) { + log_oom(); + goto finish; + } + + r = sd_bus_get_property( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Scope", + "ControlGroup", + &error, + &reply, + "s"); + + if (r < 0) { + log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r)); + goto finish; + } + + r = sd_bus_message_read(reply, "s", &cgroup); + if (r < 0) { + bus_log_parse_error(r); + goto finish; + } + + root = strdup(cgroup); + if (!root) { + log_oom(); + goto finish; + } + + } else + r = cg_get_root_path(&root); + if (r < 0) { + log_error("Failed to get %s path: %s", + arg_machine ? "machine" : "root", strerror(-r)); + goto finish; } - r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, t, NULL, 0, arg_kernel_threads, arg_all); - free(root); + r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, + arg_kernel_threads, output_flags); } - - free(p); } - if (r < 0) - log_error("Failed to list cgroup tree: %s", strerror(-r)); - - retval = EXIT_SUCCESS; + if (r < 0) { + log_error("Failed to list cgroup tree %s: %s", root, strerror(-r)); + retval = EXIT_FAILURE; + } else + retval = EXIT_SUCCESS; finish: pager_close();