blob: 9ad9c37f2c3e0b998741bd60df06bf18f581d4f9 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/exception.h>
#include <zircon/syscalls/object.h>
#include <pretty/sizes.h>
#include <task-utils/get.h>
#include <task-utils/walker.h>
#include "ps_internal.h"
static void print_help(FILE* f) {
fprintf(f, "Usage: ps [options]\n");
fprintf(f, "Options:\n");
fprintf(f, " -J Only show jobs in the output\n");
// -T for compatibility with linux ps
fprintf(f, " -T Include threads in the output\n");
fprintf(f, " --units=? Fix all sizes to the named unit\n");
fprintf(f, " where ? is one of [BkMGTPE]\n");
fprintf(f, " --job=? Show the given job and subjobs\n");
fprintf(f, " where ? is the job id.\n");
}
int main(int argc, char** argv) {
ps_options_t options = {.also_show_threads = false, .only_show_jobs = false, .format_unit = 0};
zx_status_t status;
zx_handle_t target_job = ZX_HANDLE_INVALID;
for (int i = 1; i < argc; ++i) {
const char* arg = argv[i];
if (!strcmp(arg, "--help")) {
print_help(stdout);
return 0;
}
if (!strcmp(arg, "-J")) {
options.only_show_jobs = true;
} else if (!strcmp(arg, "-T")) {
options.also_show_threads = true;
} else if (!strncmp(arg, "--units=", sizeof("--units=") - 1)) {
options.format_unit = arg[sizeof("--units=") - 1];
} else if (!strncmp(arg, "--job=", sizeof("--job=") - 1)) {
int jobid = atoi(arg + sizeof("--job=") - 1);
zx_obj_type_t type;
status = get_task_by_koid(jobid, &type, &target_job);
if (status != ZX_OK) {
fprintf(stderr, "ERROR: get_task_by_koid failed: %s (%d)\n", zx_status_get_string(status),
status);
return 1;
}
if (type != ZX_OBJ_TYPE_JOB) {
fprintf(stderr, "ERROR: object with koid %d is not a job\n", jobid);
return 1;
}
} else {
fprintf(stderr, "Unknown option: %s\n", arg);
print_help(stderr);
return 1;
}
}
// If we have a target job, only walk the target subtree. Otherwise walk from root.
if (target_job != ZX_HANDLE_INVALID) {
status = show_job_tree(target_job, &options);
zx_handle_close(target_job);
} else {
status = show_all_jobs(&options);
}
if (status != ZX_OK) {
fprintf(stderr, "WARNING: failed to walk the job tree: %s (%d)\n", zx_status_get_string(status),
status);
return 1;
}
return 0;
}