Introduce libxo to procstat(1)

Reviewed by:	rodrigc, bapt
Approved by:	marcel (mentor)
Relnotes:	yes
Sponsored by:	ScaleEngine Inc.
Differential Revision:	https://reviews.freebsd.org/D2446
This commit is contained in:
allanjude 2015-09-05 17:02:01 +00:00
parent 791763d67e
commit 4a886231b3
17 changed files with 654 additions and 243 deletions

View File

@ -17,6 +17,6 @@ SRCS= procstat.c \
procstat_threads.c \
procstat_vm.c
LIBADD+= util procstat
LIBADD+= procstat xo util sbuf
.include <bsd.prog.mk>

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 18, 2015
.Dd September 5, 2015
.Dt PROCSTAT 1
.Os
.Sh NAME
@ -33,6 +33,7 @@
.Nd get detailed process information
.Sh SYNOPSIS
.Nm
.Op Fl -libxo
.Op Fl CHhn
.Op Fl w Ar interval
.Op Fl b | c | e | f | i | j | k | l | r | s | S | t | v | x
@ -52,6 +53,13 @@ By default, basic process statistics are printed; one of the following
options may be specified in order to select more detailed process information
for printing:
.Bl -tag -width indent
.It Fl -libxo
Generate output via
.Xr libxo 3
in a selection of different human and machine readable formats.
See
.Xr xo_parse_args 3
for details on command line arguments.
.It Fl b
Display binary information for the process.
.It Fl c
@ -531,16 +539,19 @@ auxiliary vector value
.Xr cap_enter 2 ,
.Xr cap_rights_limit 2 ,
.Xr libprocstat 3 ,
.Xr libxo 3 ,
.Xr xo_parse_args 3 ,
.Xr ddb 4 ,
.Xr stack 9
.Sh AUTHORS
.An Robert N M Watson
.An Robert N M Watson Aq Mt rwatson@FreeBSD.org .
.br
.Xr libxo 3
support was added by
.An -nosplit
Allan Jude
.Aq Mt allanjude@FreeBSD.org .
.Sh BUGS
Some field values may include spaces, which limits the extent to which the
output of
.Nm
may be mechanically parsed.
.Pp
The display of open file or memory mapping pathnames is implemented using the
kernel's name cache.
If a file system does not use the name cache, or the path to a file is not in

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007, 2011 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -47,17 +48,24 @@ static void
usage(void)
{
fprintf(stderr, "usage: procstat [-CHhn] [-M core] [-N system] "
"[-w interval] \n");
fprintf(stderr, " [-b | -c | -e | -f | -i | -j | -k | "
"-l | -r | -s | -S | -t | -v | -x]\n");
fprintf(stderr, " [-a | pid | core ...]\n");
xo_error("usage: procstat [-CHhn] [-M core] [-N system] "
"[-w interval]\n"
" [-b | -c | -e | -f | -i | -j | -k | "
"-l | -r | -s | -S | -t | -v | -x]\n"
" [-a | pid | core ...]\n");
xo_finish();
exit(EX_USAGE);
}
static void
procstat(struct procstat *prstat, struct kinfo_proc *kipp)
{
char *pidstr = NULL;
asprintf(&pidstr, "%d", kipp->ki_pid);
if (pidstr == NULL)
xo_errc(1, ENOMEM, "Failed to allocate memory in procstat()");
xo_open_container(pidstr);
if (bflag)
procstat_bin(prstat, kipp);
@ -89,6 +97,9 @@ procstat(struct procstat *prstat, struct kinfo_proc *kipp)
procstat_cs(prstat, kipp);
else
procstat_basic(kipp);
xo_close_container(pidstr);
free(pidstr);
}
/*
@ -126,10 +137,14 @@ main(int argc, char *argv[])
pid_t pid;
char *dummy;
char *nlistf, *memf;
const char *xocontainer;
int cnt;
interval = 0;
memf = nlistf = NULL;
argc = xo_parse_args(argc, argv);
xocontainer = "basic";
while ((ch = getopt(argc, argv, "CHN:M:abcefijklhrsStvw:x")) != -1) {
switch (ch) {
case 'C':
@ -148,6 +163,7 @@ main(int argc, char *argv[])
break;
case 'S':
Sflag++;
xocontainer = "cs";
break;
case 'a':
aflag++;
@ -155,34 +171,42 @@ main(int argc, char *argv[])
case 'b':
bflag++;
xocontainer = "binary";
break;
case 'c':
cflag++;
xocontainer = "arguments";
break;
case 'e':
eflag++;
xocontainer = "environment";
break;
case 'f':
fflag++;
xocontainer = "files";
break;
case 'i':
iflag++;
xocontainer = "signals";
break;
case 'j':
jflag++;
xocontainer = "thread_signals";
break;
case 'k':
kflag++;
xocontainer = "kstack";
break;
case 'l':
lflag++;
xocontainer = "rlimit";
break;
case 'n':
@ -195,18 +219,22 @@ main(int argc, char *argv[])
case 'r':
rflag++;
xocontainer = "rusage";
break;
case 's':
sflag++;
xocontainer = "credentials";
break;
case 't':
tflag++;
xocontainer = "threads";
break;
case 'v':
vflag++;
xocontainer = "vm";
break;
case 'w':
@ -220,6 +248,7 @@ main(int argc, char *argv[])
case 'x':
xflag++;
xocontainer = "auxv";
break;
case '?':
@ -254,18 +283,23 @@ main(int argc, char *argv[])
else
prstat = procstat_open_sysctl();
if (prstat == NULL)
errx(1, "procstat_open()");
xo_errx(1, "procstat_open()");
do {
xo_set_version(PROCSTAT_XO_VERSION);
xo_open_container("procstat");
xo_open_container(xocontainer);
if (aflag) {
p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
if (p == NULL)
errx(1, "procstat_getprocs()");
xo_errx(1, "procstat_getprocs()");
kinfo_proc_sort(p, cnt);
for (i = 0; i < cnt; i++) {
procstat(prstat, &p[i]);
/* Suppress header after first process. */
hflag = 1;
xo_flush();
}
procstat_freeprocs(prstat, p);
}
@ -276,9 +310,10 @@ main(int argc, char *argv[])
usage();
pid = l;
p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt);
p = procstat_getprocs(prstat, KERN_PROC_PID,
pid, &cnt);
if (p == NULL)
errx(1, "procstat_getprocs()");
xo_errx(1, "procstat_getprocs()");
if (cnt != 0)
procstat(prstat, p);
procstat_freeprocs(prstat, p);
@ -291,7 +326,7 @@ main(int argc, char *argv[])
p = procstat_getprocs(cprstat, KERN_PROC_PID,
-1, &cnt);
if (p == NULL)
errx(1, "procstat_getprocs()");
xo_errx(1, "procstat_getprocs()");
if (cnt != 0)
procstat(cprstat, p);
procstat_freeprocs(cprstat, p);
@ -300,9 +335,15 @@ main(int argc, char *argv[])
/* Suppress header after first process. */
hflag = 1;
}
xo_close_container(xocontainer);
xo_close_container("procstat");
xo_finish();
if (interval)
sleep(interval);
} while (interval);
procstat_close(prstat);
exit(0);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,9 +27,13 @@
* $FreeBSD$
*/
#include <libxo/xo.h>
#ifndef PROCSTAT_H
#define PROCSTAT_H
#define PROCSTAT_XO_VERSION "1"
extern int hflag, nflag, Cflag, Hflag;
struct kinfo_proc;

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -40,40 +41,56 @@
#include "procstat.h"
static void
do_args(struct procstat *procstat, struct kinfo_proc *kipp, int env)
void
procstat_args(struct procstat *procstat, struct kinfo_proc *kipp)
{
int i;
char **args;
if (!hflag) {
printf("%5s %-16s %-53s\n", "PID", "COMM",
env ? "ENVIRONMENT" : "ARGS");
xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ARGS");
}
args = env ? procstat_getenvv(procstat, kipp, 0) :
procstat_getargv(procstat, kipp, 0);
args = procstat_getargv(procstat, kipp, 0);
printf("%5d %-16s", kipp->ki_pid, kipp->ki_comm);
xo_emit("{k:process_id/%5d/%d} {:command/%-16s/%s}", kipp->ki_pid,
kipp->ki_comm);
if (args == NULL) {
printf(" -\n");
xo_emit(" {d:args/-}\n");
return;
}
xo_open_list("arguments");
for (i = 0; args[i] != NULL; i++)
printf(" %s", args[i]);
printf("\n");
}
void
procstat_args(struct procstat *procstat, struct kinfo_proc *kipp)
{
do_args(procstat, kipp, 0);
xo_emit(" {l:args/%s}", args[i]);
xo_close_list("arguments");
xo_emit("\n");
}
void
procstat_env(struct procstat *procstat, struct kinfo_proc *kipp)
{
do_args(procstat, kipp, 1);
int i;
char **envs;
if (!hflag) {
xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT");
}
envs = procstat_getenvv(procstat, kipp, 0);
xo_emit("{k:process_id/%5d/%d} {:command/%-16s/%s}", kipp->ki_pid,
kipp->ki_comm);
if (envs == NULL) {
xo_emit(" {d:env/-}\n");
return;
}
xo_open_list("environment");
for (i = 0; envs[i] != NULL; i++)
xo_emit(" {l:env/%s}", envs[i]);
xo_close_list("environment");
xo_emit("\n");
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011 Mikolaj Golub
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,11 +44,6 @@
#include "procstat.h"
#define PRINT(name, spec, val) \
printf("%s %-16s " #spec "\n", prefix, #name, (val))
#define PRINT_UNKNOWN(type, val) \
printf("%s %16ld %#lx\n", prefix, (long)type, (u_long)(val))
void
procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp)
{
@ -56,12 +52,18 @@ procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp)
static char prefix[256];
if (!hflag)
printf("%5s %-16s %-16s %-16s\n", "PID", "COMM", "AUXV", "VALUE");
xo_emit("{T:/%5s %-16s %-16s %-16s}\n", "PID", "COMM", "AUXV",
"VALUE");
auxv = procstat_getauxv(procstat, kipp, &count);
if (auxv == NULL)
return;
snprintf(prefix, sizeof(prefix), "%5d %-16s", kipp->ki_pid,
snprintf(prefix, sizeof(prefix), "%5d %-16s", kipp->ki_pid,
kipp->ki_comm);
xo_emit("{e:process_id/%5d/%d}{e:command/%-16s/%s}", kipp->ki_pid,
kipp->ki_comm);
for (i = 0; i < count; i++) {
switch(auxv[i].a_type) {
case AT_NULL:
@ -69,92 +71,119 @@ procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp)
case AT_IGNORE:
break;
case AT_EXECFD:
PRINT(AT_EXECFD, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EXECFD/%ld}\n",
prefix, "AT_EXECFD", (long)auxv[i].a_un.a_val);
break;
case AT_PHDR:
PRINT(AT_PHDR, %p, auxv[i].a_un.a_ptr);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHDR/%p}\n",
prefix, "AT_PHDR", auxv[i].a_un.a_ptr);
break;
case AT_PHENT:
PRINT(AT_PHENT, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHENT/%ld}\n",
prefix, "AT_PHENT", (long)auxv[i].a_un.a_val);
break;
case AT_PHNUM:
PRINT(AT_PHNUM, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHNUM/%ld}\n",
prefix, "AT_PHNUM", (long)auxv[i].a_un.a_val);
break;
case AT_PAGESZ:
PRINT(AT_PAGESZ, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PAGESZ/%ld}\n",
prefix, "AT_PAGESZ", (long)auxv[i].a_un.a_val);
break;
case AT_BASE:
PRINT(AT_BASE, %p, auxv[i].a_un.a_ptr);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_BASE/%p}\n",
prefix, "AT_BASE", auxv[i].a_un.a_ptr);
break;
case AT_FLAGS:
PRINT(AT_FLAGS, %#lx, (u_long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_FLAGS/%#lx}\n",
prefix, "AT_FLAGS", (u_long)auxv[i].a_un.a_val);
break;
case AT_ENTRY:
PRINT(AT_ENTRY, %p, auxv[i].a_un.a_ptr);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ENTRY/%p}\n",
prefix, "AT_ENTRY", auxv[i].a_un.a_ptr);
break;
#ifdef AT_NOTELF
case AT_NOTELF:
PRINT(AT_NOTELF, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_NOTELF/%ld}\n",
prefix, "AT_NOTELF", (long)auxv[i].a_un.a_val);
break;
#endif
#ifdef AT_UID
case AT_UID:
PRINT(AT_UID, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_UID/%ld}\n",
prefix, "AT_UID", (long)auxv[i].a_un.a_val);
break;
#endif
#ifdef AT_EUID
case AT_EUID:
PRINT(AT_EUID, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EUID/%ld}\n",
prefix, "AT_EUID", (long)auxv[i].a_un.a_val);
break;
#endif
#ifdef AT_GID
case AT_GID:
PRINT(AT_GID, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_GID/%ld}\n",
prefix, "AT_GID", (long)auxv[i].a_un.a_val);
break;
#endif
#ifdef AT_EGID
case AT_EGID:
PRINT(AT_EGID, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EGID/%ld}\n",
prefix, "AT_EGID", (long)auxv[i].a_un.a_val);
break;
#endif
case AT_EXECPATH:
PRINT(AT_EXECPATH, %p, auxv[i].a_un.a_ptr);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EXECPATH/%p}\n",
prefix, "AT_EXECPATH", auxv[i].a_un.a_ptr);
break;
case AT_CANARY:
PRINT(AT_CANARY, %p, auxv[i].a_un.a_ptr);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_CANARY/%p}\n",
prefix, "AT_CANARY", auxv[i].a_un.a_ptr);
break;
case AT_CANARYLEN:
PRINT(AT_CANARYLEN, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_CANARYLEN/%ld}\n",
prefix, "AT_CANARYLEN", (long)auxv[i].a_un.a_val);
break;
case AT_OSRELDATE:
PRINT(AT_OSRELDATE, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_OSRELDATE/%ld}\n",
prefix, "AT_OSRELDATE", (long)auxv[i].a_un.a_val);
break;
case AT_NCPUS:
PRINT(AT_NCPUS, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_NCPUS/%ld}\n",
prefix, "AT_NCPUS", (long)auxv[i].a_un.a_val);
break;
case AT_PAGESIZES:
PRINT(AT_PAGESIZES, %p, auxv[i].a_un.a_ptr);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PAGESIZES/%p}\n",
prefix, "AT_PAGESIZES", auxv[i].a_un.a_ptr);
break;
case AT_PAGESIZESLEN:
PRINT(AT_PAGESIZESLEN, %ld, (long)auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
"{:AT_PAGESIZESLEN/%ld}\n", prefix,
"AT_PAGESIZESLEN", (long)auxv[i].a_un.a_val);
break;
case AT_STACKPROT:
if ((auxv[i].a_un.a_val & VM_PROT_EXECUTE) != 0)
PRINT(AT_STACKPROT, %s, "NONEXECUTABLE");
xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
"{:AT_STACKPROT/%s}\n", prefix,
"AT_STACKPROT", "NONEXECUTABLE");
else
PRINT(AT_STACKPROT, %s, "EXECUTABLE");
xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
"{:AT_STACKPROT/%s}\n", prefix,
"AT_STACKPROT", "EXECUTABLE");
break;
#ifdef AT_TIMEKEEP
case AT_TIMEKEEP:
PRINT(AT_TIMEKEEP, %p, auxv[i].a_un.a_ptr);
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_TIMEKEEP/%p}\n",
prefix, "AT_TIMEKEEP", auxv[i].a_un.a_ptr);
break;
#endif
default:
PRINT_UNKNOWN(auxv[i].a_type, auxv[i].a_un.a_val);
xo_emit("{dw:/%s}{Lw:/%16ld/%ld}{:UNKNOWN/%#lx}\n",
prefix, auxv[i].a_type, auxv[i].a_un.a_val);
break;
}
}
printf("\n");
xo_emit("\n");
procstat_freeauxv(procstat, auxv);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -42,24 +43,26 @@ procstat_basic(struct kinfo_proc *kipp)
{
if (!hflag)
printf("%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s\n",
xo_emit("{T:/%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s}\n",
"PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN",
"WCHAN", "EMUL", "COMM");
printf("%5d ", kipp->ki_pid);
printf("%5d ", kipp->ki_ppid);
printf("%5d ", kipp->ki_pgid);
printf("%5d ", kipp->ki_sid);
printf("%5d ", kipp->ki_tsid);
printf("%3d ", kipp->ki_numthreads);
printf("%-8s ", strlen(kipp->ki_login) ? kipp->ki_login : "-");
xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{:parent_process_id/%5d/%d} ", kipp->ki_ppid);
xo_emit("{:process_group_id/%5d/%d} ", kipp->ki_pgid);
xo_emit("{:session_id/%5d/%d} ", kipp->ki_sid);
xo_emit("{:terminal_session_id/%5d/%d} ", kipp->ki_tsid);
xo_emit("{:threads/%3d/%d} ", kipp->ki_numthreads);
xo_emit("{:login/%-8s/%s} ", strlen(kipp->ki_login) ?
kipp->ki_login : "-");
if (kipp->ki_kiflag & KI_LOCKBLOCK) {
printf("*%-8s ", strlen(kipp->ki_lockname) ?
xo_emit("{:lockname/*%-8s/%s} ", strlen(kipp->ki_lockname) ?
kipp->ki_lockname : "-");
} else {
printf("%-9s ", strlen(kipp->ki_wmesg) ?
xo_emit("{:wait_channel/%-9s/%s} ", strlen(kipp->ki_wmesg) ?
kipp->ki_wmesg : "-");
}
printf("%-13s ", strcmp(kipp->ki_emul, "null") ? kipp->ki_emul : "-");
printf("%-12s\n", kipp->ki_comm);
xo_emit("{:emulation/%-13s/%s} ", strcmp(kipp->ki_emul, "null") ?
kipp->ki_emul : "-");
xo_emit("{:command/%-12s/%s}\n", kipp->ki_comm);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -46,7 +47,8 @@ procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp)
static char pathname[PATH_MAX];
if (!hflag)
printf("%5s %-16s %8s %s\n", "PID", "COMM", "OSREL", "PATH");
xo_emit("{T:/%5s %-16s %8s %s}\n", "PID", "COMM", "OSREL",
"PATH");
if (procstat_getpathname(prstat, kipp, pathname, sizeof(pathname)) != 0)
return;
@ -55,8 +57,8 @@ procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp)
if (procstat_getosrel(prstat, kipp, &osrel) != 0)
return;
printf("%5d ", kipp->ki_pid);
printf("%-16s ", kipp->ki_comm);
printf("%8d ", osrel);
printf("%s\n", pathname);
xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
xo_emit("{:osrel/%8d/%d} ", osrel);
xo_emit("{:pathname/%s}\n", pathname);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007-2008 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -48,21 +49,22 @@ procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp)
gid_t *groups;
if (!hflag)
printf("%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s\n",
xo_emit("{T:/%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s}\n",
"PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID",
"SVGID", "UMASK", "FLAGS", "GROUPS");
printf("%5d ", kipp->ki_pid);
printf("%-16s ", kipp->ki_comm);
printf("%5d ", kipp->ki_uid);
printf("%5d ", kipp->ki_ruid);
printf("%5d ", kipp->ki_svuid);
printf("%5d ", kipp->ki_groups[0]);
printf("%5d ", kipp->ki_rgid);
printf("%5d ", kipp->ki_svgid);
printf("%5s ", get_umask(procstat, kipp));
printf("%s", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ? "C" : "-");
printf(" ");
xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
xo_emit("{:uid/%5d} ", kipp->ki_uid);
xo_emit("{:ruid/%5d} ", kipp->ki_ruid);
xo_emit("{:svuid/%5d} ", kipp->ki_svuid);
xo_emit("{:group/%5d} ", kipp->ki_groups[0]);
xo_emit("{:rgid/%5d} ", kipp->ki_rgid);
xo_emit("{:svgid/%5d} ", kipp->ki_svgid);
xo_emit("{:umask/%5s} ", get_umask(procstat, kipp));
xo_emit("{:cr_flags/%s}", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ?
"C" : "-");
xo_emit("{P: }");
groups = NULL;
/*
@ -76,12 +78,14 @@ procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp)
ngroups = kipp->ki_ngroups;
groups = kipp->ki_groups;
}
xo_open_list("groups");
for (i = 0; i < ngroups; i++)
printf("%s%d", (i > 0) ? "," : "", groups[i]);
xo_emit("{D:/%s}{l:groups/%d}", (i > 0) ? "," : "", groups[i]);
if (groups != kipp->ki_groups)
procstat_freegroups(procstat, groups);
printf("\n");
xo_close_list("groups");
xo_emit("\n");
}
static const char *

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -28,6 +29,7 @@
#include <sys/param.h>
#include <sys/cpuset.h>
#include <sys/sbuf.h>
#include <sys/sysctl.h>
#include <sys/user.h>
@ -46,11 +48,12 @@ procstat_cs(struct procstat *procstat, struct kinfo_proc *kipp)
cpusetid_t cs;
cpuset_t mask;
struct kinfo_proc *kip;
struct sbuf *cpusetbuf;
unsigned int count, i;
int once, twice, lastcpu, cpu;
if (!hflag)
printf("%5s %6s %-16s %-16s %2s %4s %-7s\n", "PID",
xo_emit("{T:/%5s %6s %-16s %-16s %2s %4s %-7s}\n", "PID",
"TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK");
kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
@ -60,49 +63,57 @@ procstat_cs(struct procstat *procstat, struct kinfo_proc *kipp)
kinfo_proc_sort(kip, count);
for (i = 0; i < count; i++) {
kipp = &kip[i];
printf("%5d ", kipp->ki_pid);
printf("%6d ", kipp->ki_tid);
printf("%-16s ", strlen(kipp->ki_comm) ?
xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid);
xo_emit("{:command/%-16s/%s} ", strlen(kipp->ki_comm) ?
kipp->ki_comm : "-");
printf("%-16s ", (strlen(kipp->ki_tdname) &&
xo_emit("{:thread_name/%-16s/%s} ", (strlen(kipp->ki_tdname) &&
(strcmp(kipp->ki_comm, kipp->ki_tdname) != 0)) ?
kipp->ki_tdname : "-");
if (kipp->ki_oncpu != 255)
printf("%3d ", kipp->ki_oncpu);
xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu);
else if (kipp->ki_lastcpu != 255)
printf("%3d ", kipp->ki_lastcpu);
xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu);
else
printf("%3s ", "-");
xo_emit("{:cpu/%3s/%s} ", "-");
if (cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID,
kipp->ki_tid, &cs) != 0) {
cs = CPUSET_INVALID;
}
printf("%4d ", cs);
xo_emit("{:cpu_set_id/%4d/%d} ", cs);
if ((cs != CPUSET_INVALID) &&
(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
kipp->ki_tid, sizeof(mask), &mask) == 0)) {
lastcpu = -1;
once = 0;
twice = 0;
cpusetbuf = sbuf_new_auto();
for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
if (CPU_ISSET(cpu, &mask)) {
if (once == 0) {
printf("%d", cpu);
sbuf_printf(cpusetbuf, "%d",
cpu);
once = 1;
} else if (cpu == lastcpu + 1) {
twice = 1;
} else if (twice == 1) {
printf("-%d,%d", lastcpu, cpu);
sbuf_printf(cpusetbuf, "-%d,%d",
lastcpu, cpu);
twice = 0;
} else
printf(",%d", cpu);
sbuf_printf(cpusetbuf, ",%d",
cpu);
lastcpu = cpu;
}
}
if (once && twice)
printf("-%d", lastcpu);
sbuf_printf(cpusetbuf, "-%d", lastcpu);
if (sbuf_finish(cpusetbuf) != 0)
xo_err(1, "Could not generate output");
xo_emit("{:cpu_set/%s}", sbuf_data(cpusetbuf));
sbuf_delete(cpusetbuf);
}
printf("\n");
xo_emit("\n");
}
procstat_freeprocs(procstat, kip);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007-2011 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -123,15 +124,6 @@ addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
}
}
static void
print_address(struct sockaddr_storage *ss)
{
char addr[PATH_MAX];
addr_to_string(ss, addr, sizeof(addr));
printf("%s", addr);
}
static struct cap_desc {
uint64_t cd_right;
const char *cd_desc;
@ -273,19 +265,22 @@ print_capability(cap_rights_t *rightsp, u_int capwidth)
width = 0;
for (i = width_capability(rightsp); i < capwidth; i++) {
if (i != 0)
printf(" ");
xo_emit(" ");
else
printf("-");
xo_emit("-");
}
xo_open_list("capabilities");
for (i = 0; i < cap_desc_count; i++) {
if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) {
printf("%s%s", count ? "," : "", cap_desc[i].cd_desc);
xo_emit("{D:/%s}{l:capabilities/%s}", count ? "," : "",
cap_desc[i].cd_desc);
width += strlen(cap_desc[i].cd_desc);
if (count)
width++;
count++;
}
}
xo_close_list("capabilities");
}
void
@ -298,6 +293,8 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
struct vnstat vn;
u_int capwidth, width;
int error;
char src_addr[PATH_MAX];
char dst_addr[PATH_MAX];
/*
* To print the header in capability mode, we need to know the width
@ -319,84 +316,103 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
if (!hflag) {
if (Cflag)
printf("%5s %-16s %5s %1s %-8s %-*s "
"%-3s %-12s\n", "PID", "COMM", "FD", "T",
xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s "
"%-3s %-12s}\n", "PID", "COMM", "FD", "T",
"FLAGS", capwidth, "CAPABILITIES", "PRO",
"NAME");
else
printf("%5s %-16s %5s %1s %1s %-8s "
"%3s %7s %-3s %-12s\n", "PID", "COMM", "FD", "T",
xo_emit("{T:/%5s %-16s %5s %1s %1s %-8s "
"%3s %7s %-3s %-12s}\n", "PID", "COMM", "FD", "T",
"V", "FLAGS", "REF", "OFFSET", "PRO", "NAME");
}
if (head == NULL)
return;
xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
xo_open_list("files");
STAILQ_FOREACH(fst, head, next) {
printf("%5d ", kipp->ki_pid);
printf("%-16s ", kipp->ki_comm);
xo_open_instance("files");
xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
printf(" ctty ");
xo_emit("{P: }{:fd/%s} ", "ctty");
else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
printf(" cwd ");
xo_emit("{P: }{:fd/%s} ", "cwd");
else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
printf(" jail ");
xo_emit("{P: }{:fd/%s} ", "jail");
else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
printf(" root ");
xo_emit("{P: }{:fd/%s} ", "root");
else if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
printf(" text ");
xo_emit("{P: }{:fd/%s} ", "text");
else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
printf("trace ");
xo_emit("{:fd/%s} ", "trace");
else
printf("%5d ", fst->fs_fd);
xo_emit("{:fd/%5d} ", fst->fs_fd);
switch (fst->fs_type) {
case PS_FST_TYPE_VNODE:
str = "v";
xo_emit("{eq:fd_type/vnode}");
break;
case PS_FST_TYPE_SOCKET:
str = "s";
xo_emit("{eq:fd_type/socket}");
break;
case PS_FST_TYPE_PIPE:
str = "p";
xo_emit("{eq:fd_type/pipe}");
break;
case PS_FST_TYPE_FIFO:
str = "f";
xo_emit("{eq:fd_type/fifo}");
break;
case PS_FST_TYPE_KQUEUE:
str = "k";
xo_emit("{eq:fd_type/kqueue}");
break;
case PS_FST_TYPE_CRYPTO:
str = "c";
xo_emit("{eq:fd_type/crypto}");
break;
case PS_FST_TYPE_MQUEUE:
str = "m";
xo_emit("{eq:fd_type/mqueue}");
break;
case PS_FST_TYPE_SHM:
str = "h";
xo_emit("{eq:fd_type/shm}");
break;
case PS_FST_TYPE_PTS:
str = "t";
xo_emit("{eq:fd_type/pts}");
break;
case PS_FST_TYPE_SEM:
str = "e";
xo_emit("{eq:fd_type/sem}");
break;
case PS_FST_TYPE_NONE:
str = "?";
xo_emit("{eq:fd_type/none}");
break;
case PS_FST_TYPE_UNKNOWN:
default:
str = "?";
xo_emit("{eq:fd_type/unknown}");
break;
}
printf("%1s ", str);
xo_emit("{d:fd_type/%1s/%s} ", str);
if (!Cflag) {
str = "-";
if (fst->fs_type == PS_FST_TYPE_VNODE) {
@ -405,74 +421,118 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
switch (vn.vn_type) {
case PS_FST_VTYPE_VREG:
str = "r";
xo_emit("{eq:vode_type/regular}");
break;
case PS_FST_VTYPE_VDIR:
str = "d";
xo_emit("{eq:vode_type/directory}");
break;
case PS_FST_VTYPE_VBLK:
str = "b";
xo_emit("{eq:vode_type/block}");
break;
case PS_FST_VTYPE_VCHR:
str = "c";
xo_emit("{eq:vode_type/character}");
break;
case PS_FST_VTYPE_VLNK:
str = "l";
xo_emit("{eq:vode_type/link}");
break;
case PS_FST_VTYPE_VSOCK:
str = "s";
xo_emit("{eq:vode_type/socket}");
break;
case PS_FST_VTYPE_VFIFO:
str = "f";
xo_emit("{eq:vode_type/fifo}");
break;
case PS_FST_VTYPE_VBAD:
str = "x";
xo_emit("{eq:vode_type/revoked_device}");
break;
case PS_FST_VTYPE_VNON:
str = "?";
xo_emit("{eq:vode_type/non}");
break;
case PS_FST_VTYPE_UNKNOWN:
default:
str = "?";
xo_emit("{eq:vode_type/unknown}");
break;
}
}
printf("%1s ", str);
xo_emit("{d:vnode_type/%1s/%s} ", str);
}
printf("%s", fst->fs_fflags & PS_FST_FFLAG_READ ? "r" : "-");
printf("%s", fst->fs_fflags & PS_FST_FFLAG_WRITE ? "w" : "-");
printf("%s", fst->fs_fflags & PS_FST_FFLAG_APPEND ? "a" : "-");
printf("%s", fst->fs_fflags & PS_FST_FFLAG_ASYNC ? "s" : "-");
printf("%s", fst->fs_fflags & PS_FST_FFLAG_SYNC ? "f" : "-");
printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : "-");
printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-");
printf("%s", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-");
printf(" ");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_READ ?
"r" : "-");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_WRITE ?
"w" : "-");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_APPEND ?
"a" : "-");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_ASYNC ?
"s" : "-");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_SYNC ?
"f" : "-");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ?
"n" : "-");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_DIRECT ?
"d" : "-");
xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ?
"l" : "-");
xo_emit(" ");
xo_open_list("fd_flags");
if (fst->fs_fflags & PS_FST_FFLAG_READ)
xo_emit("{elq:fd_flags/read}");
if (fst->fs_fflags & PS_FST_FFLAG_WRITE)
xo_emit("{elq:fd_flags/write}");
if (fst->fs_fflags & PS_FST_FFLAG_APPEND)
xo_emit("{elq:fd_flags/append}");
if (fst->fs_fflags & PS_FST_FFLAG_ASYNC)
xo_emit("{elq:fd_flags/async}");
if (fst->fs_fflags & PS_FST_FFLAG_SYNC)
xo_emit("{elq:fd_flags/fsync}");
if (fst->fs_fflags & PS_FST_FFLAG_NONBLOCK)
xo_emit("{elq:fd_flags/nonblocking}");
if (fst->fs_fflags & PS_FST_FFLAG_DIRECT)
xo_emit("{elq:fd_flags/direct_io}");
if (fst->fs_fflags & PS_FST_FFLAG_HASLOCK)
xo_emit("{elq:fd_flags/lock_held}");
xo_close_list("fd_flags");
if (!Cflag) {
if (fst->fs_ref_count > -1)
printf("%3d ", fst->fs_ref_count);
xo_emit("{:ref_count/%3d/%d} ",
fst->fs_ref_count);
else
printf("%3c ", '-');
xo_emit("{q:ref_count/%3c/%c} ", '-');
if (fst->fs_offset > -1)
printf("%7jd ", (intmax_t)fst->fs_offset);
xo_emit("{:offset/%7jd/%jd} ",
(intmax_t)fst->fs_offset);
else
printf("%7c ", '-');
xo_emit("{q:offset/%7c/%c} ", '-');
}
if (Cflag) {
print_capability(&fst->fs_cap_rights, capwidth);
printf(" ");
xo_emit(" ");
}
switch (fst->fs_type) {
case PS_FST_TYPE_SOCKET:
error = procstat_get_socket_info(procstat, fst, &sock, NULL);
error = procstat_get_socket_info(procstat, fst, &sock,
NULL);
if (error != 0)
break;
printf("%-3s ",
xo_emit("{:protocol/%-3s/%s} ",
protocol_to_string(sock.dom_family,
sock.type, sock.proto));
/*
@ -487,22 +547,30 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
(struct sockaddr_un *)&sock.sa_local;
if (sun->sun_path[0] != 0)
print_address(&sock.sa_local);
addr_to_string(&sock.sa_local,
src_addr, sizeof(src_addr));
else
print_address(&sock.sa_peer);
addr_to_string(&sock.sa_peer,
src_addr, sizeof(src_addr));
xo_emit("{:path/%s}", src_addr);
} else {
print_address(&sock.sa_local);
printf(" ");
print_address(&sock.sa_peer);
addr_to_string(&sock.sa_local, src_addr,
sizeof(src_addr));
addr_to_string(&sock.sa_peer, dst_addr,
sizeof(dst_addr));
xo_emit("{:path/%s %s}", src_addr, dst_addr);
}
break;
default:
printf("%-3s ", "-");
printf("%-18s", fst->fs_path != NULL ? fst->fs_path : "-");
xo_emit("{:protocol/%-3s/%s} ", "-");
xo_emit("{:path/%-18s/%s}", fst->fs_path != NULL ?
fst->fs_path : "-");
}
printf("\n");
xo_emit("\n");
xo_close_instance("files");
}
xo_close_list("files");
procstat_freefiles(procstat, head);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -105,6 +106,42 @@ kstack_cleanup(const char *old, char *new, int kflag)
*cp_new = '\0';
}
static void
kstack_cleanup_encoded(const char *old, char *new, int kflag)
{
enum trace_state old_ts, ts;
const char *cp_old;
char *cp_new, *cp_loop, *cp_tofree, *cp_line;
ts = TS_FRAMENUM;
if (kflag == 1) {
for (cp_old = old, cp_new = new; *cp_old != '\0'; cp_old++) {
switch (*cp_old) {
case '\n':
*cp_new = *cp_old;
cp_new++;
case ' ':
case '+':
old_ts = ts;
ts = kstack_nextstate(old_ts);
continue;
}
if (ts == TS_FUNC) {
*cp_new = *cp_old;
cp_new++;
}
}
cp_tofree = cp_loop = strdup(new);
} else
cp_tofree = cp_loop = strdup(old);
while ((cp_line = strsep(&cp_loop, "\n")) != NULL) {
if (strlen(cp_line) != 0 && *cp_line != 127)
xo_emit("{le:token/%s}", cp_line);
}
*cp_new = '\0';
free(cp_tofree);
}
/*
* Sort threads by tid.
*/
@ -129,12 +166,12 @@ procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp, int kflag)
{
struct kinfo_kstack *kkstp, *kkstp_free;
struct kinfo_proc *kip, *kip_free;
char trace[KKST_MAXLEN];
char trace[KKST_MAXLEN], encoded_trace[KKST_MAXLEN];
unsigned int i, j;
unsigned int kip_count, kstk_count;
if (!hflag)
printf("%5s %6s %-16s %-16s %-29s\n", "PID", "TID", "COMM",
xo_emit("{T:/%5s %6s %-16s %-16s %-29s}\n", "PID", "TID", "COMM",
"TDNAME", "KSTACK");
kkstp = kkstp_free = procstat_getkstack(procstat, kipp, &kstk_count);
@ -169,27 +206,27 @@ procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp, int kflag)
if (kipp == NULL)
continue;
printf("%5d ", kipp->ki_pid);
printf("%6d ", kkstp->kkst_tid);
printf("%-16s ", kipp->ki_comm);
printf("%-16s ", (strlen(kipp->ki_tdname) &&
xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{:thread_id/%6d/%d} ", kkstp->kkst_tid);
xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
xo_emit("{:thread_name/%-16s/%s} ", (strlen(kipp->ki_tdname) &&
(strcmp(kipp->ki_comm, kipp->ki_tdname) != 0)) ?
kipp->ki_tdname : "-");
switch (kkstp->kkst_state) {
case KKST_STATE_RUNNING:
printf("%-29s\n", "<running>");
xo_emit("{:state/%-29s/%s}\n", "<running>");
continue;
case KKST_STATE_SWAPPED:
printf("%-29s\n", "<swapped>");
xo_emit("{:state/%-29s/%s}\n", "<swapped>");
continue;
case KKST_STATE_STACKOK:
break;
default:
printf("%-29s\n", "<unknown>");
xo_emit("{:state/%-29s/%s}\n", "<unknown>");
continue;
}
@ -199,7 +236,10 @@ procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp, int kflag)
* returns to spaces.
*/
kstack_cleanup(kkstp->kkst_trace, trace, kflag);
printf("%-29s\n", trace);
xo_open_list("trace");
kstack_cleanup_encoded(kkstp->kkst_trace, encoded_trace, kflag);
xo_close_list("trace");
xo_emit("{d:trace/%-29s}\n", trace);
}
procstat_freekstack(procstat, kkstp_free);
procstat_freeprocs(procstat, kip_free);

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011 Mikolaj Golub
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -93,15 +94,33 @@ procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp)
int i;
if (!hflag) {
printf("%5s %-16s %-16s %16s %16s\n",
xo_emit("{T:/%5s %-16s %-16s %16s %16s}\n",
"PID", "COMM", "RLIMIT", "SOFT ", "HARD ");
}
xo_emit("{ek:process_id/%5d}{e:command/%-16s/%s}", kipp->ki_pid,
kipp->ki_comm);
for (i = 0; i < RLIM_NLIMITS; i++) {
if (procstat_getrlimit(prstat, kipp, i, &rlimit) == -1)
return;
printf("%5d %-16s %-16s ", kipp->ki_pid, kipp->ki_comm,
xo_emit("{dk:process_id/%5d} {d:command/%-16s} "
"{d:rlimit_param/%-16s} ", kipp->ki_pid, kipp->ki_comm,
rlimit_param[i].name);
printf("%16s ", humanize_rlimit(i, rlimit.rlim_cur));
printf("%16s\n", humanize_rlimit(i, rlimit.rlim_max));
xo_open_container(rlimit_param[i].name);
if (rlimit.rlim_cur == RLIM_INFINITY)
xo_emit("{e:soft_limit/infinity}");
else
xo_emit("{e:soft_limit/%U}", rlimit.rlim_cur);
if (rlimit.rlim_max == RLIM_INFINITY)
xo_emit("{e:hard_limit/infinity}");
else
xo_emit("{e:hard_limit/%U}", rlimit.rlim_max);
xo_close_container(rlimit_param[i].name);
xo_emit("{d:rlim_cur/%16s} ",
humanize_rlimit(i, rlimit.rlim_cur));
xo_emit("{d:rlim_max/%16s}\n",
humanize_rlimit(i, rlimit.rlim_max));
}
}

View File

@ -1,6 +1,7 @@
/*-
* Copyright (c) 2012 Hudson River Trading LLC
* Written by: John H. Baldwin <jhb@FreeBSD.org>
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -35,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <libprocstat.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <libutil.h>
#include "procstat.h"
@ -79,7 +81,7 @@ format_time(struct timeval *tv)
else if (days > 0)
used += snprintf(buffer, sizeof(buffer), "%u days ", days);
snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u ",
snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u",
hours, minutes, seconds, (unsigned int)tv->tv_usec);
return (buffer);
}
@ -103,10 +105,10 @@ static void
print_prefix(struct kinfo_proc *kipp)
{
printf("%5d ", kipp->ki_pid);
xo_emit("{d:process_id/%5d/%d} ", kipp->ki_pid);
if (Hflag)
printf("%6d ", kipp->ki_tid);
printf("%-16s ", kipp->ki_comm);
xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
}
static void
@ -114,21 +116,48 @@ print_rusage(struct kinfo_proc *kipp)
{
long *lp;
unsigned int i;
char *field, *threadid;
print_prefix(kipp);
printf("%-14s %32s\n", "user time",
xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "user time",
format_time(&kipp->ki_rusage.ru_utime));
print_prefix(kipp);
printf("%-14s %32s\n", "system time",
xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "system time",
format_time(&kipp->ki_rusage.ru_stime));
if (Hflag) {
asprintf(&threadid, "%d", kipp->ki_tid);
if (threadid == NULL)
xo_errc(1, ENOMEM,
"Failed to allocate memory in print_rusage()");
xo_open_container(threadid);
xo_emit("{e:thread_id/%d}", kipp->ki_tid);
} else {
xo_emit("{e:process_id/%d}", kipp->ki_pid);
xo_emit("{e:command/%s}", kipp->ki_comm);
}
xo_emit("{e:user time/%s}", format_time(&kipp->ki_rusage.ru_utime));
xo_emit("{e:system time/%s}", format_time(&kipp->ki_rusage.ru_stime));
lp = &kipp->ki_rusage.ru_maxrss;
for (i = 0; i < nitems(rusage_info); i++) {
print_prefix(kipp);
printf("%-32s %14s\n", rusage_info[i].ri_name,
asprintf(&field, "{e:%s/%%D}", rusage_info[i].ri_name);
if (field == NULL)
xo_errc(1, ENOMEM,
"Failed to allocate memory in print_rusage()");
xo_emit(field, *lp);
free(field);
xo_emit("{d:resource/%-32s} {d:usage/%14s}\n",
rusage_info[i].ri_name,
format_value(*lp, rusage_info[i].ri_humanize,
rusage_info[i].ri_scale));
rusage_info[i].ri_scale));
lp++;
}
if (Hflag) {
xo_close_container(threadid);
free(threadid);
}
}
void
@ -138,10 +167,10 @@ procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp)
unsigned int count, i;
if (!hflag) {
printf("%5s ", "PID");
xo_emit("{d:ta/%5s} ", "PID");
if (Hflag)
printf("%6s ", "TID");
printf("%-16s %-32s %14s\n", "COMM", "RESOURCE",
xo_emit("{d:tb/%6s} ", "TID");
xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE",
"VALUE ");
}
@ -150,12 +179,19 @@ procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp)
return;
}
xo_emit("{e:process_id/%d}", kipp->ki_pid);
xo_emit("{e:command/%s}", kipp->ki_comm);
xo_open_container("threads");
kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
kipp->ki_pid, &count);
if (kip == NULL)
return;
kinfo_proc_sort(kip, count);
for (i = 0; i < count; i++)
for (i = 0; i < count; i++) {
print_rusage(&kip[i]);
}
xo_close_container("threads");
procstat_freeprocs(procstat, kip);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2010 Konstantin Belousov
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -51,70 +52,129 @@ procstat_print_signame(int sig)
strlcpy(name, sys_signame[sig], sizeof(name));
for (i = 0; name[i] != 0; i++)
name[i] = toupper(name[i]);
printf("%-7s ", name);
xo_emit("{d:signal/%-7s/%s} ", name);
xo_open_container(name);
} else {
xo_emit("{d:signal/%-7d/%d} ", sig);
snprintf(name, 12, "%d", sig);
xo_open_container(name);
}
}
static void
procstat_close_signame(int sig)
{
char name[12];
int i;
if (!nflag && sig < sys_nsig) {
strlcpy(name, sys_signame[sig], sizeof(name));
for (i = 0; name[i] != 0; i++)
name[i] = toupper(name[i]);
xo_close_container(name);
} else
printf("%-7d ", sig);
snprintf(name, 12, "%d", sig);
xo_close_container(name);
}
static void
procstat_print_sig(const sigset_t *set, int sig, char flag)
{
printf("%c", sigismember(set, sig) ? flag : '-');
xo_emit("{d:sigmember/%c}", sigismember(set, sig) ? flag : '-');
switch (flag) {
case 'B':
xo_emit("{en:mask/%s}", sigismember(set, sig) ?
"true" : "false");
break;
case 'C':
xo_emit("{en:catch/%s}", sigismember(set, sig) ?
"true" : "false");
break;
case 'P':
xo_emit("{en:list/%s}", sigismember(set, sig) ?
"true" : "false");
break;
case 'I':
xo_emit("{en:ignore/%s}", sigismember(set, sig) ?
"true" : "false");
break;
default:
xo_emit("{en:unknown/%s}", sigismember(set, sig) ?
"true" : "false");
break;
}
}
void
procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
{
int j;
pid_t pid;
pid = kipp->ki_pid;
if (!hflag)
printf("%5s %-16s %-7s %4s\n", "PID", "COMM", "SIG", "FLAGS");
xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG",
"FLAGS");
xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
xo_open_container("signals");
for (j = 1; j <= _SIG_MAXSIG; j++) {
printf("%5d ", pid);
printf("%-16s ", kipp->ki_comm);
xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
procstat_print_signame(j);
printf(" ");
xo_emit(" ");
procstat_print_sig(&kipp->ki_siglist, j, 'P');
procstat_print_sig(&kipp->ki_sigignore, j, 'I');
procstat_print_sig(&kipp->ki_sigcatch, j, 'C');
printf("\n");
procstat_close_signame(j);
xo_emit("\n");
}
xo_close_container("signals");
}
void
procstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp)
{
struct kinfo_proc *kip;
pid_t pid;
int j;
unsigned int count, i;
char *threadid;
pid = kipp->ki_pid;
if (!hflag)
printf("%5s %6s %-16s %-7s %4s\n", "PID", "TID", "COMM",
xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM",
"SIG", "FLAGS");
kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
pid, &count);
kipp->ki_pid, &count);
if (kip == NULL)
return;
xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
xo_open_container("threads");
kinfo_proc_sort(kip, count);
for (i = 0; i < count; i++) {
kipp = &kip[i];
asprintf(&threadid, "%d", kipp->ki_tid);
if (threadid == NULL)
xo_errc(1, ENOMEM, "Failed to allocate memory in "
"procstat_threads_sigs()");
xo_open_container(threadid);
xo_emit("{e:thread_id/%6d/%d}", kipp->ki_tid);
xo_open_container("signals");
for (j = 1; j <= _SIG_MAXSIG; j++) {
printf("%5d ", pid);
printf("%6d ", kipp->ki_tid);
printf("%-16s ", kipp->ki_comm);
xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
procstat_print_signame(j);
printf(" ");
xo_emit(" ");
procstat_print_sig(&kipp->ki_siglist, j, 'P');
procstat_print_sig(&kipp->ki_sigmask, j, 'B');
printf("\n");
procstat_close_signame(j);
xo_emit("\n");
}
xo_close_container("signals");
xo_close_container(threadid);
free(threadid);
}
xo_close_container("threads");
procstat_freeprocs(procstat, kip);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -45,11 +46,17 @@ procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp)
struct kinfo_proc *kip;
unsigned int count, i;
const char *str;
char *threadid;
if (!hflag)
printf("%5s %6s %-16s %-16s %2s %4s %-7s %-9s\n", "PID",
xo_emit("{T:/%5s %6s %-16s %-16s %2s %4s %-7s %-9s}\n", "PID",
"TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN");
xo_emit("{ek:process_id/%d}", kipp->ki_pid);
xo_emit("{e:command/%s}", strlen(kipp->ki_comm) ?
kipp->ki_comm : "-");
xo_open_container("threads");
kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
kipp->ki_pid, &count);
if (kip == NULL)
@ -57,20 +64,25 @@ procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp)
kinfo_proc_sort(kip, count);
for (i = 0; i < count; i++) {
kipp = &kip[i];
printf("%5d ", kipp->ki_pid);
printf("%6d ", kipp->ki_tid);
printf("%-16s ", strlen(kipp->ki_comm) ?
asprintf(&threadid, "%d", kipp->ki_tid);
if (threadid == NULL)
xo_errc(1, ENOMEM, "Failed to allocate memory in "
"procstat_threads()");
xo_open_container(threadid);
xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid);
xo_emit("{d:command/%-16s/%s} ", strlen(kipp->ki_comm) ?
kipp->ki_comm : "-");
printf("%-16s ", (strlen(kipp->ki_tdname) &&
xo_emit("{:thread_name/%-16s/%s} ", (strlen(kipp->ki_tdname) &&
(strcmp(kipp->ki_comm, kipp->ki_tdname) != 0)) ?
kipp->ki_tdname : "-");
if (kipp->ki_oncpu != 255)
printf("%3d ", kipp->ki_oncpu);
xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu);
else if (kipp->ki_lastcpu != 255)
printf("%3d ", kipp->ki_lastcpu);
xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu);
else
printf("%3s ", "-");
printf("%4d ", kipp->ki_pri.pri_level);
xo_emit("{:cpu/%3s/%s} ", "-");
xo_emit("{:priority/%4d/%d} ", kipp->ki_pri.pri_level);
switch (kipp->ki_stat) {
case SRUN:
str = "run";
@ -104,15 +116,19 @@ procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp)
str = "??";
break;
}
printf("%-7s ", str);
xo_emit("{:run_state/%-7s/%s} ", str);
if (kipp->ki_kiflag & KI_LOCKBLOCK) {
printf("*%-8s ", strlen(kipp->ki_lockname) ?
xo_emit("{:lock_name/*%-8s/%s} ",
strlen(kipp->ki_lockname) ?
kipp->ki_lockname : "-");
} else {
printf("%-9s ", strlen(kipp->ki_wmesg) ?
kipp->ki_wmesg : "-");
xo_emit("{:wait_channel/%-9s/%s} ",
strlen(kipp->ki_wmesg) ? kipp->ki_wmesg : "-");
}
printf("\n");
xo_close_container(threadid);
free(threadid);
xo_emit("\n");
}
xo_close_container("threads");
procstat_freeprocs(procstat, kip);
}

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -46,70 +47,118 @@ procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
struct kinfo_vmentry *freep, *kve;
int ptrwidth;
int i, cnt;
const char *str;
const char *str, *lstr;
ptrwidth = 2*sizeof(void *) + 2;
if (!hflag)
printf("%5s %*s %*s %3s %4s %4s %3s %3s %-4s %-2s %-s\n",
xo_emit("{T:/%5s %*s %*s %3s %4s %4s %3s %3s %-4s %-2s %-s}\n",
"PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
"PRES", "REF", "SHD", "FLAG", "TP", "PATH");
xo_emit("{ek:process_id/%d}", kipp->ki_pid);
freep = procstat_getvmmap(procstat, kipp, &cnt);
if (freep == NULL)
return;
xo_open_list("vm");
for (i = 0; i < cnt; i++) {
xo_open_instance("vm");
kve = &freep[i];
printf("%5d ", kipp->ki_pid);
printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_start);
printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_end);
printf("%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
printf("%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-");
printf("%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-");
printf("%4d ", kve->kve_resident);
printf("%4d ", kve->kve_private_resident);
printf("%3d ", kve->kve_ref_count);
printf("%3d ", kve->kve_shadow_count);
printf("%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-");
printf("%-1s", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" :
"-");
printf("%-1s", kve->kve_flags & KVME_FLAG_SUPER ? "S" : "-");
printf("%-1s ", kve->kve_flags & KVME_FLAG_GROWS_UP ? "U" :
kve->kve_flags & KVME_FLAG_GROWS_DOWN ? "D" : "-");
xo_emit("{dk:process_id/%5d} ", kipp->ki_pid);
xo_emit("{d:kve_start/%#*jx} ", ptrwidth,
(uintmax_t)kve->kve_start);
xo_emit("{d:kve_end/%#*jx} ", ptrwidth,
(uintmax_t)kve->kve_end);
xo_emit("{e:kve_start/%#jx}", (uintmax_t)kve->kve_start);
xo_emit("{e:kve_end/%#jx}", (uintmax_t)kve->kve_end);
xo_emit("{d:read/%s}", kve->kve_protection & KVME_PROT_READ ?
"r" : "-");
xo_emit("{d:write/%s}", kve->kve_protection & KVME_PROT_WRITE ?
"w" : "-");
xo_emit("{d:exec/%s} ", kve->kve_protection & KVME_PROT_EXEC ?
"x" : "-");
xo_open_container("kve_protection");
xo_emit("{en:read/%s}", kve->kve_protection & KVME_PROT_READ ?
"true" : "false");
xo_emit("{en:write/%s}", kve->kve_protection & KVME_PROT_WRITE ?
"true" : "false");
xo_emit("{en:exec/%s}", kve->kve_protection & KVME_PROT_EXEC ?
"true" : "false");
xo_close_container("kve_protection");
xo_emit("{:kve_resident/%4d/%d} ", kve->kve_resident);
xo_emit("{:kve_private_resident/%4d/%d} ",
kve->kve_private_resident);
xo_emit("{:kve_ref_count/%3d/%d} ", kve->kve_ref_count);
xo_emit("{:kve_shadow_count/%3d/%d} ", kve->kve_shadow_count);
xo_emit("{d:copy_on_write/%-1s}", kve->kve_flags &
KVME_FLAG_COW ? "C" : "-");
xo_emit("{d:need_copy/%-1s}", kve->kve_flags &
KVME_FLAG_NEEDS_COPY ? "N" : "-");
xo_emit("{d:super_pages/%-1s}", kve->kve_flags &
KVME_FLAG_SUPER ? "S" : "-");
xo_emit("{d:grows_down/%-1s} ", kve->kve_flags &
KVME_FLAG_GROWS_UP ? "U" : kve->kve_flags &
KVME_FLAG_GROWS_DOWN ? "D" : "-");
xo_open_container("kve_flags");
xo_emit("{en:copy_on_write/%s}", kve->kve_flags &
KVME_FLAG_COW ? "true" : "false");
xo_emit("{en:needs_copy/%s}", kve->kve_flags &
KVME_FLAG_NEEDS_COPY ? "true" : "false");
xo_emit("{en:super_pages/%s}", kve->kve_flags &
KVME_FLAG_SUPER ? "true" : "false");
xo_emit("{en:grows_up/%s}", kve->kve_flags &
KVME_FLAG_GROWS_UP ? "true" : "false");
xo_emit("{en:grows_down/%s}", kve->kve_flags &
KVME_FLAG_GROWS_DOWN ? "true" : "false");
xo_close_container("kve_flags");
switch (kve->kve_type) {
case KVME_TYPE_NONE:
str = "--";
lstr = "none";
break;
case KVME_TYPE_DEFAULT:
str = "df";
lstr = "default";
break;
case KVME_TYPE_VNODE:
str = "vn";
lstr = "vnode";
break;
case KVME_TYPE_SWAP:
str = "sw";
lstr = "swap";
break;
case KVME_TYPE_DEVICE:
str = "dv";
lstr = "device";
break;
case KVME_TYPE_PHYS:
str = "ph";
lstr = "physical";
break;
case KVME_TYPE_DEAD:
str = "dd";
lstr = "dead";
break;
case KVME_TYPE_SG:
str = "sg";
lstr = "scatter/gather";
break;
case KVME_TYPE_MGTDEVICE:
str = "md";
lstr = "managed_device";
break;
case KVME_TYPE_UNKNOWN:
default:
str = "??";
lstr = "unknown";
break;
}
printf("%-2s ", str);
printf("%-s\n", kve->kve_path);
xo_emit("{d:kve_type/%-2s} ", str);
xo_emit("{e:kve_type/%s}", lstr);
xo_emit("{:kve_path/%-s/%s}\n", kve->kve_path);
xo_close_instance("vm");
}
xo_close_list("vm");
free(freep);
}