Index: head/usr.bin/procstat/procstat.c =================================================================== --- head/usr.bin/procstat/procstat.c (revision 366209) +++ head/usr.bin/procstat/procstat.c (revision 366210) @@ -1,626 +1,627 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007, 2011 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * Copyright (c) 2017 Dell EMC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "procstat.h" enum { PS_CMP_NORMAL = 0x00, PS_CMP_PLURAL = 0x01, PS_CMP_SUBSTR = 0x02 }; struct procstat_cmd { const char *command; const char *xocontainer; const char *usage; void (*cmd)(struct procstat *, struct kinfo_proc *); void (*opt)(int, char * const *); int cmp; }; int procstat_opts = 0; static void cmdopt_none(int argc, char * const argv[]); static void cmdopt_verbose(int argc, char * const argv[]); static void cmdopt_signals(int argc, char * const argv[]); static void cmdopt_rusage(int argc, char * const argv[]); static void cmdopt_files(int argc, char * const argv[]); static void cmdopt_cpuset(int argc, char * const argv[]); static const char *progname; /* aliased program parameters and arguments * - usage field is abused to hold the pointer to the function * displaying program usage */ static const struct procstat_cmd pacmd_table[] = { /* arguments are the same as for pwdx: pid or core file */ { "pargs", "args", NULL, &procstat_pargs, &cmdopt_none, PS_CMP_NORMAL | PS_MODE_COMPAT }, { "penv", "env", NULL, &procstat_penv, &cmdopt_none, PS_CMP_NORMAL | PS_MODE_COMPAT }, { "pwdx", "pwd", NULL, &procstat_pwdx, &cmdopt_none, PS_CMP_NORMAL | PS_MODE_COMPAT } }; /* procstat parameters and arguments */ static const struct procstat_cmd cmd_table[] = { { "argument", "arguments", NULL, &procstat_args, &cmdopt_none, PS_CMP_PLURAL | PS_CMP_SUBSTR }, { "auxv", "auxv", NULL, &procstat_auxv, &cmdopt_none, PS_CMP_NORMAL }, { "basic", "basic", NULL, &procstat_basic, &cmdopt_none, PS_CMP_NORMAL }, { "binary", "binary", NULL, &procstat_bin, &cmdopt_none, PS_CMP_SUBSTR }, { "cpuset", "cs", NULL, &procstat_cs, &cmdopt_cpuset, PS_CMP_NORMAL }, { "cs", "cs", NULL, &procstat_cs, &cmdopt_cpuset, PS_CMP_NORMAL }, { "credential", "credentials", NULL, &procstat_cred, &cmdopt_none, PS_CMP_PLURAL | PS_CMP_SUBSTR }, { "environment", "environment", NULL, &procstat_env, &cmdopt_none, PS_CMP_SUBSTR }, { "fd", "files", "[-C]", &procstat_files, &cmdopt_files, PS_CMP_PLURAL }, { "file", "files", "[-C]", &procstat_files, &cmdopt_files, PS_CMP_PLURAL }, { "kstack", "kstack", "[-v]", &procstat_kstack, &cmdopt_verbose, PS_CMP_NORMAL }, { "pargs", "args", NULL, &procstat_pargs, &cmdopt_none, PS_CMP_NORMAL }, { "penv", "env", NULL, &procstat_penv, &cmdopt_none, PS_CMP_NORMAL }, { "ptlwpinfo", "ptlwpinfo", NULL, &procstat_ptlwpinfo, &cmdopt_none, PS_CMP_NORMAL }, { "pwdx", "pwd", NULL, &procstat_pwdx, &cmdopt_none, PS_CMP_NORMAL }, { "rlimit", "rlimit", NULL, &procstat_rlimit, &cmdopt_none, PS_CMP_NORMAL }, { "rusage", "rusage", "[-Ht]", &procstat_rusage, &cmdopt_rusage, PS_CMP_NORMAL }, { "sigfastblock", "sigfastblock", NULL, &procstat_sigfastblock, &cmdopt_none, PS_CMP_NORMAL }, { "signal", "signals", "[-n]", &procstat_sigs, &cmdopt_signals, PS_CMP_PLURAL | PS_CMP_SUBSTR }, { "thread", "threads", NULL, &procstat_threads, &cmdopt_none, PS_CMP_PLURAL }, { "tsignal", "thread_signals", "[-n]", &procstat_threads_sigs, &cmdopt_signals, PS_CMP_PLURAL | PS_CMP_SUBSTR }, { "vm", "vm", NULL, &procstat_vm, &cmdopt_none, PS_CMP_NORMAL } }; static void usage(const struct procstat_cmd *cmd) { size_t i, l; int multi; if (cmd == NULL || (cmd->cmp & PS_MODE_COMPAT) == 0) { xo_error("usage: procstat [--libxo] [-h] [-M core] [-N system]" " [-w interval] command\n" " [pid ... | core ...]\n" " procstat [--libxo] -a [-h] [-M core] [-N system] " " [-w interval] command\n" " procstat [--libxo] [-h] [-M core] [-N system]" " [-w interval]\n" " [-S | -b | -c | -e | -f [-C] | -i [-n] | " "-j [-n] | -k [-k] |\n" " -l | -r [-H] | -s | -t | -v | -x] " "[pid ... | core ...]\n" " procstat [--libxo] -a [-h] [-M core] [-N system]" " [-w interval]\n" " [-S | -b | -c | -e | -f [-C] | -i [-n] | " "-j [-n] | -k [-k] |\n" " -l | -r [-H] | -s | -t | -v | -x]\n" " procstat [--libxo] -L [-h] [-M core] [-N system] core ...\n" "Available commands:\n"); for (i = 0, l = nitems(cmd_table); i < l; i++) { multi = i + 1 < l && cmd_table[i].cmd == cmd_table[i + 1].cmd; xo_error(" %s%s%s", multi ? "[" : "", cmd_table[i].command, (cmd_table[i].cmp & PS_CMP_PLURAL) ? "(s)" : ""); for (; i + 1 < l && cmd_table[i].cmd == cmd_table[i + 1].cmd; i++) xo_error(" | %s%s", cmd_table[i + 1].command, (cmd_table[i].cmp & PS_CMP_PLURAL) ? "(s)" : ""); if (multi) xo_error("]"); if (cmd_table[i].usage != NULL) xo_error(" %s", cmd_table[i].usage); xo_error("\n"); } } else { xo_error("usage: %s [--libxo] pid ...\n", progname); } xo_finish(); exit(EX_USAGE); } static void procstat(const struct procstat_cmd *cmd, 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); cmd->cmd(prstat, kipp); xo_close_container(pidstr); free(pidstr); } /* * Sort processes first by pid and then tid. */ static int kinfo_proc_compare(const void *a, const void *b) { int i; i = ((const struct kinfo_proc *)a)->ki_pid - ((const struct kinfo_proc *)b)->ki_pid; if (i != 0) return (i); i = ((const struct kinfo_proc *)a)->ki_tid - ((const struct kinfo_proc *)b)->ki_tid; return (i); } void kinfo_proc_sort(struct kinfo_proc *kipp, int count) { qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare); } const char * kinfo_proc_thread_name(const struct kinfo_proc *kipp) { static char name[MAXCOMLEN+1]; strlcpy(name, kipp->ki_tdname, sizeof(name)); strlcat(name, kipp->ki_moretdname, sizeof(name)); if (name[0] == '\0' || strcmp(kipp->ki_comm, name) == 0) { name[0] = '-'; name[1] = '\0'; } return (name); } static const struct procstat_cmd * getcmdbyprogname(const char *pprogname) { const char *ca; size_t i, len; if (pprogname == NULL) return (NULL); len = strlen(pprogname); for (i = 0; i < nitems(pacmd_table); i++) { ca = pacmd_table[i].command; if (ca != NULL && strcmp(ca, pprogname) == 0) return (&pacmd_table[i]); } return (NULL); } static const struct procstat_cmd * getcmd(const char *str) { const struct procstat_cmd *cmd; size_t i, l; int cmp, s; if (str == NULL) return (NULL); cmd = NULL; if ((l = strlen(str)) == 0) return (getcmd("basic")); s = l > 1 && strcasecmp(str + l - 1, "s") == 0; for (i = 0; i < nitems(cmd_table); i++) { /* * After the first match substring matches are disabled, * allowing subsequent full matches to take precedence. */ if (cmd == NULL && (cmd_table[i].cmp & PS_CMP_SUBSTR)) cmp = strncasecmp(str, cmd_table[i].command, l - ((cmd_table[i].cmp & PS_CMP_PLURAL) && s ? 1 : 0)); else if ((cmd_table[i].cmp & PS_CMP_PLURAL) && s && l == strlen(cmd_table[i].command) + 1) cmp = strncasecmp(str, cmd_table[i].command, l - 1); else cmp = strcasecmp(str, cmd_table[i].command); if (cmp == 0) cmd = &cmd_table[i]; } return (cmd); } int main(int argc, char *argv[]) { struct kinfo_proc *p; const struct procstat_cmd *cmd; struct procstat *prstat, *cprstat; char *dummy, *nlistf, *memf; const char *xocontainer; long l; pid_t pid; int aflag, ch, cnt, i, interval; interval = 0; cmd = NULL; memf = nlistf = NULL; aflag = 0; argc = xo_parse_args(argc, argv); progname = getprogname(); cmd = getcmdbyprogname(progname); while ((ch = getopt(argc, argv, "abCcefHhijkLlM:N:nrSstvw:x")) != -1) { switch (ch) { case 'a': aflag++; break; case 'b': if (cmd != NULL) usage(cmd); cmd = getcmd("binary"); break; case 'C': procstat_opts |= PS_OPT_CAPABILITIES; break; case 'c': if (cmd != NULL) usage(cmd); cmd = getcmd("arguments"); break; case 'e': if (cmd != NULL) usage(cmd); cmd = getcmd("environment"); break; case 'f': if (cmd != NULL) usage(cmd); cmd = getcmd("files"); break; case 'H': procstat_opts |= PS_OPT_PERTHREAD; break; case 'h': procstat_opts |= PS_OPT_NOHEADER; break; case 'i': if (cmd != NULL) usage(cmd); cmd = getcmd("signals"); break; case 'j': if (cmd != NULL) usage(cmd); cmd = getcmd("tsignals"); break; case 'k': if (cmd != NULL && cmd->cmd == procstat_kstack) { if ((procstat_opts & PS_OPT_VERBOSE) != 0) usage(cmd); procstat_opts |= PS_OPT_VERBOSE; } else { if (cmd != NULL) usage(cmd); cmd = getcmd("kstack"); } break; case 'L': if (cmd != NULL) usage(cmd); cmd = getcmd("ptlwpinfo"); break; case 'l': if (cmd != NULL) usage(cmd); cmd = getcmd("rlimit"); break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'n': procstat_opts |= PS_OPT_SIGNUM; break; case 'r': if (cmd != NULL) usage(cmd); cmd = getcmd("rusage"); break; case 'S': if (cmd != NULL) usage(cmd); cmd = getcmd("cpuset"); break; case 's': if (cmd != NULL) usage(cmd); cmd = getcmd("credentials"); break; case 't': if (cmd != NULL) usage(cmd); cmd = getcmd("threads"); break; case 'v': if (cmd != NULL) usage(cmd); cmd = getcmd("vm"); break; case 'w': l = strtol(optarg, &dummy, 10); if (*dummy != '\0') usage(cmd); if (l < 1 || l > INT_MAX) usage(cmd); interval = l; break; case 'x': if (cmd != NULL) usage(cmd); cmd = getcmd("auxv"); break; case '?': default: usage(cmd); } } argc -= optind; argv += optind; if (cmd == NULL && argv[0] != NULL) cmd = getcmd(argv[0]); if (cmd != NULL) { if ((procstat_opts & PS_SUBCOMMAND_OPTS) != 0) usage(cmd); if (cmd->opt != NULL) { optreset = 1; optind = 1; cmd->opt(argc, argv); if ((cmd->cmp & PS_MODE_COMPAT) == 0) { argc -= optind; argv += optind; } } else { argc -= 1; argv += 1; } } else { cmd = getcmd("basic"); } if (cmd->cmd != procstat_files && (procstat_opts & PS_OPT_CAPABILITIES) != 0 && (cmd->cmp & PS_MODE_COMPAT) == 0) usage(cmd); /* Must specify either the -a flag or a list of pids. */ if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0)) usage(cmd); if (memf != NULL) prstat = procstat_open_kvm(nlistf, memf); else prstat = procstat_open_sysctl(); if (prstat == NULL) xo_errx(1, "procstat_open()"); do { xocontainer = cmd->xocontainer != NULL ? cmd->xocontainer : cmd->command; xo_set_version(PROCSTAT_XO_VERSION); xo_open_container(progname); xo_open_container(xocontainer); if (aflag) { p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); kinfo_proc_sort(p, cnt); for (i = 0; i < cnt; i++) { procstat(cmd, prstat, &p[i]); /* Suppress header after first process. */ procstat_opts |= PS_OPT_NOHEADER; xo_flush(); } procstat_freeprocs(prstat, p); } for (i = 0; i < argc; i++) { l = strtol(argv[i], &dummy, 10); if (*dummy == '\0') { if (l < 0) usage(cmd); pid = l; p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(cmd, prstat, p); procstat_freeprocs(prstat, p); } else { if ((cmd->cmp & PS_MODE_COMPAT) == 0) { cprstat = procstat_open_core(argv[i]); if (cprstat == NULL) { warnx("procstat_open()"); continue; } p = procstat_getprocs(cprstat, KERN_PROC_PID, -1, &cnt); if (p == NULL) { xo_errx(1, "procstat_getprocs()"); } if (cnt != 0) procstat(cmd, cprstat, p); procstat_freeprocs(cprstat, p); procstat_close(cprstat); } else { usage(cmd); } } if ((cmd->cmp & PS_MODE_COMPAT) == 0) { /* Suppress header after first process. */ procstat_opts |= PS_OPT_NOHEADER; } } xo_close_container(xocontainer); xo_close_container(progname); xo_finish(); if (interval) sleep(interval); } while (interval); procstat_close(prstat); exit(0); } void cmdopt_none(int argc, char * const argv[]) { int ch; while ((ch = getopt(argc, argv, "")) != -1) { switch (ch) { case '?': default: usage(NULL); } } } void cmdopt_verbose(int argc, char * const argv[]) { int ch; while ((ch = getopt(argc, argv, "v")) != -1) { switch (ch) { case 'v': procstat_opts |= PS_OPT_VERBOSE; break; case '?': default: usage(NULL); } } } void cmdopt_signals(int argc, char * const argv[]) { int ch; while ((ch = getopt(argc, argv, "n")) != -1) { switch (ch) { case 'n': procstat_opts |= PS_OPT_SIGNUM; break; case '?': default: usage(NULL); } } } void cmdopt_rusage(int argc, char * const argv[]) { int ch; while ((ch = getopt(argc, argv, "Ht")) != -1) { switch (ch) { case 'H': /* FALLTHROUGH */ case 't': procstat_opts |= PS_OPT_PERTHREAD; break; case '?': default: usage(NULL); } } } void cmdopt_files(int argc, char * const argv[]) { int ch; while ((ch = getopt(argc, argv, "C")) != -1) { switch (ch) { case 'C': procstat_opts |= PS_OPT_CAPABILITIES; break; case '?': default: usage(NULL); } } } void cmdopt_cpuset(int argc, char * const argv[]) { procstat_opts |= PS_OPT_PERTHREAD; cmdopt_none(argc, argv); } Index: head/usr.bin/procstat/procstat_args.c =================================================================== --- head/usr.bin/procstat/procstat_args.c (revision 366209) +++ head/usr.bin/procstat/procstat_args.c (revision 366210) @@ -1,98 +1,99 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "procstat.h" void procstat_args(struct procstat *procstat, struct kinfo_proc *kipp) { int i; char **args; if ((procstat_opts & PS_OPT_NOHEADER) == 0) { xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ARGS"); } args = procstat_getargv(procstat, kipp, 0); xo_emit("{k:process_id/%5d/%d} {:command/%-16s/%s}", kipp->ki_pid, kipp->ki_comm); if (args == NULL) { xo_emit(" {d:args/-}\n"); return; } xo_open_list("arguments"); for (i = 0; args[i] != NULL; i++) xo_emit(" {l:args/%s}", args[i]); xo_close_list("arguments"); xo_emit("\n"); } void procstat_env(struct procstat *procstat, struct kinfo_proc *kipp) { int i; char **envs; if ((procstat_opts & PS_OPT_NOHEADER) == 0) { 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"); } Index: head/usr.bin/procstat/procstat_auxv.c =================================================================== --- head/usr.bin/procstat/procstat_auxv.c (revision 366209) +++ head/usr.bin/procstat/procstat_auxv.c (revision 366210) @@ -1,245 +1,246 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Mikolaj Golub * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "procstat.h" void procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp) { Elf_Auxinfo *auxv; u_int count, i; static char prefix[256]; if ((procstat_opts & PS_OPT_NOHEADER) == 0) 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, 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: return; case AT_IGNORE: break; case AT_EXECFD: 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: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHDR/%p}\n", prefix, "AT_PHDR", auxv[i].a_un.a_ptr); break; case AT_PHENT: 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: 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: 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: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_BASE/%p}\n", prefix, "AT_BASE", auxv[i].a_un.a_ptr); break; case AT_FLAGS: 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: 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: 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: 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: 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: 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: 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: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EXECPATH/%p}\n", prefix, "AT_EXECPATH", auxv[i].a_un.a_ptr); break; case AT_CANARY: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_CANARY/%p}\n", prefix, "AT_CANARY", auxv[i].a_un.a_ptr); break; case AT_CANARYLEN: 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: 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: 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: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PAGESIZES/%p}\n", prefix, "AT_PAGESIZES", auxv[i].a_un.a_ptr); break; case AT_PAGESIZESLEN: 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) xo_emit("{dw:/%s}{Lw:/%-16s/%s}" "{:AT_STACKPROT/%s}\n", prefix, "AT_STACKPROT", "EXECUTABLE"); else xo_emit("{dw:/%s}{Lw:/%-16s/%s}" "{:AT_STACKPROT/%s}\n", prefix, "AT_STACKPROT", "NONEXECUTABLE"); break; #ifdef AT_TIMEKEEP case AT_TIMEKEEP: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_TIMEKEEP/%p}\n", prefix, "AT_TIMEKEEP", auxv[i].a_un.a_ptr); break; #endif #ifdef AT_EHDRFLAGS case AT_EHDRFLAGS: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EHDRFLAGS/%#lx}\n", prefix, "AT_EHDRFLAGS", (u_long)auxv[i].a_un.a_val); break; #endif #ifdef AT_HWCAP case AT_HWCAP: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_HWCAP/%#lx}\n", prefix, "AT_HWCAP", (u_long)auxv[i].a_un.a_val); break; #endif #ifdef AT_HWCAP2 case AT_HWCAP2: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_HWCAP2/%#lx}\n", prefix, "AT_HWCAP2", (u_long)auxv[i].a_un.a_val); break; #endif #ifdef AT_BSDFLAGS case AT_BSDFLAGS: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_BSDFLAGS/%#lx}\n", prefix, "AT_BSDFLAGS", (u_long)auxv[i].a_un.a_val); break; #endif #ifdef AT_ARGC case AT_ARGC: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ARGC/%ld}\n", prefix, "AT_ARGC", (long)auxv[i].a_un.a_val); break; #endif #ifdef AT_ARGV case AT_ARGV: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ARGV/%p}\n", prefix, "AT_ARGV", auxv[i].a_un.a_ptr); break; #endif #ifdef AT_ENVC case AT_ENVC: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ENVC/%ld}\n", prefix, "AT_ENVC", (long)auxv[i].a_un.a_val); break; #endif #ifdef AT_ENVV case AT_ENVV: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ENVV/%p}\n", prefix, "AT_ENVV", auxv[i].a_un.a_ptr); break; #endif #ifdef AT_PS_STRINGS case AT_PS_STRINGS: xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PS_STRINGS/%p}\n", prefix, "AT_PS_STRINGS", auxv[i].a_un.a_ptr); break; #endif default: xo_emit("{dw:/%s}{Lw:/%16ld/%ld}{:UNKNOWN/%#lx}\n", prefix, auxv[i].a_type, auxv[i].a_un.a_val); break; } } xo_emit("\n"); procstat_freeauxv(procstat, auxv); } Index: head/usr.bin/procstat/procstat_basic.c =================================================================== --- head/usr.bin/procstat/procstat_basic.c (revision 366209) +++ head/usr.bin/procstat/procstat_basic.c (revision 366210) @@ -1,70 +1,71 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "procstat.h" void procstat_basic(struct procstat *procstat __unused, struct kinfo_proc *kipp) { if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s}\n", "PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN", "WCHAN", "EMUL", "COMM"); 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) { xo_emit("{:lockname/*%-8s/%s} ", strlen(kipp->ki_lockname) ? kipp->ki_lockname : "-"); } else { xo_emit("{:wait_channel/%-9s/%s} ", strlen(kipp->ki_wmesg) ? kipp->ki_wmesg : "-"); } xo_emit("{:emulation/%-13s/%s} ", strcmp(kipp->ki_emul, "null") ? kipp->ki_emul : "-"); xo_emit("{:command/%-12s/%s}\n", kipp->ki_comm); } Index: head/usr.bin/procstat/procstat_bin.c =================================================================== --- head/usr.bin/procstat/procstat_bin.c (revision 366209) +++ head/usr.bin/procstat/procstat_bin.c (revision 366210) @@ -1,66 +1,67 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "procstat.h" void procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp) { int osrel; static char pathname[PATH_MAX]; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %-16s %8s %s}\n", "PID", "COMM", "OSREL", "PATH"); if (procstat_getpathname(prstat, kipp, pathname, sizeof(pathname)) != 0) return; if (strlen(pathname) == 0) strcpy(pathname, "-"); if (procstat_getosrel(prstat, kipp, &osrel) != 0) return; 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); } Index: head/usr.bin/procstat/procstat_cred.c =================================================================== --- head/usr.bin/procstat/procstat_cred.c (revision 366209) +++ head/usr.bin/procstat/procstat_cred.c (revision 366210) @@ -1,105 +1,106 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007-2008 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "procstat.h" static const char *get_umask(struct procstat *procstat, struct kinfo_proc *kipp); void procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp) { unsigned int i, ngroups; gid_t *groups; if ((procstat_opts & PS_OPT_NOHEADER) == 0) 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"); 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; /* * We may have too many groups to fit in kinfo_proc's statically * sized storage. If that occurs, attempt to retrieve them using * libprocstat. */ if (kipp->ki_cr_flags & KI_CRF_GRP_OVERFLOW) groups = procstat_getgroups(procstat, kipp, &ngroups); if (groups == NULL) { ngroups = kipp->ki_ngroups; groups = kipp->ki_groups; } xo_open_list("groups"); for (i = 0; i < ngroups; i++) xo_emit("{D:/%s}{l:groups/%d}", (i > 0) ? "," : "", groups[i]); if (groups != kipp->ki_groups) procstat_freegroups(procstat, groups); xo_close_list("groups"); xo_emit("\n"); } static const char * get_umask(struct procstat *procstat, struct kinfo_proc *kipp) { u_short fd_cmask; static char umask[4]; if (procstat_getumask(procstat, kipp, &fd_cmask) == 0) { snprintf(umask, 4, "%03o", fd_cmask); return (umask); } else { return ("-"); } } Index: head/usr.bin/procstat/procstat_cs.c =================================================================== --- head/usr.bin/procstat/procstat_cs.c (revision 366209) +++ head/usr.bin/procstat/procstat_cs.c (revision 366210) @@ -1,118 +1,119 @@ /*- * Copyright (c) 2007 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include "procstat.h" void 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 ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s}\n", "PID", "TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK"); 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++) { kipp = &kip[i]; xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid); xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid); xo_emit("{:command/%-19s/%s} ", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); xo_emit("{:thread_name/%-19s/%s} ", kinfo_proc_thread_name(kipp)); if (kipp->ki_oncpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu); else if (kipp->ki_lastcpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu); else xo_emit("{:cpu/%3s/%s} ", "-"); if (cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, kipp->ki_tid, &cs) != 0) { cs = CPUSET_INVALID; } 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) { sbuf_printf(cpusetbuf, "%d", cpu); once = 1; } else if (cpu == lastcpu + 1) { twice = 1; } else if (twice == 1) { sbuf_printf(cpusetbuf, "-%d,%d", lastcpu, cpu); twice = 0; } else sbuf_printf(cpusetbuf, ",%d", cpu); lastcpu = cpu; } } if (once && twice) 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); } xo_emit("\n"); } procstat_freeprocs(procstat, kip); } Index: head/usr.bin/procstat/procstat_files.c =================================================================== --- head/usr.bin/procstat/procstat_files.c (revision 366209) +++ head/usr.bin/procstat/procstat_files.c (revision 366210) @@ -1,599 +1,600 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007-2011 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "procstat.h" static const char * protocol_to_string(int domain, int type, int protocol) { switch (domain) { case AF_INET: case AF_INET6: switch (protocol) { case IPPROTO_TCP: return ("TCP"); case IPPROTO_UDP: return ("UDP"); case IPPROTO_ICMP: return ("ICM"); case IPPROTO_RAW: return ("RAW"); case IPPROTO_SCTP: return ("SCT"); case IPPROTO_DIVERT: return ("IPD"); default: return ("IP?"); } case AF_LOCAL: switch (type) { case SOCK_STREAM: return ("UDS"); case SOCK_DGRAM: return ("UDD"); default: return ("UD?"); } default: return ("?"); } } static void addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen) { char buffer2[INET6_ADDRSTRLEN]; struct sockaddr_in6 *sin6; struct sockaddr_in *sin; struct sockaddr_un *sun; switch (ss->ss_family) { case AF_LOCAL: sun = (struct sockaddr_un *)ss; if (strlen(sun->sun_path) == 0) strlcpy(buffer, "-", buflen); else strlcpy(buffer, sun->sun_path, buflen); break; case AF_INET: sin = (struct sockaddr_in *)ss; if (sin->sin_addr.s_addr == INADDR_ANY) snprintf(buffer, buflen, "%s:%d", "*", ntohs(sin->sin_port)); else if (inet_ntop(AF_INET, &sin->sin_addr, buffer2, sizeof(buffer2)) != NULL) snprintf(buffer, buflen, "%s:%d", buffer2, ntohs(sin->sin_port)); break; case AF_INET6: sin6 = (struct sockaddr_in6 *)ss; if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2, sizeof(buffer2)) != NULL) snprintf(buffer, buflen, "%s.%d", buffer2, ntohs(sin6->sin6_port)); else strlcpy(buffer, "-", buflen); break; default: strlcpy(buffer, "", buflen); break; } } static struct cap_desc { uint64_t cd_right; const char *cd_desc; } cap_desc[] = { /* General file I/O. */ { CAP_READ, "rd" }, { CAP_WRITE, "wr" }, { CAP_SEEK, "se" }, { CAP_MMAP, "mm" }, { CAP_CREATE, "cr" }, { CAP_FEXECVE, "fe" }, { CAP_FSYNC, "fy" }, { CAP_FTRUNCATE, "ft" }, /* VFS methods. */ { CAP_FCHDIR, "cd" }, { CAP_FCHFLAGS, "cf" }, { CAP_FCHMOD, "cm" }, { CAP_FCHOWN, "cn" }, { CAP_FCNTL, "fc" }, { CAP_FLOCK, "fl" }, { CAP_FPATHCONF, "fp" }, { CAP_FSCK, "fk" }, { CAP_FSTAT, "fs" }, { CAP_FSTATFS, "sf" }, { CAP_FUTIMES, "fu" }, { CAP_LINKAT_SOURCE, "ls" }, { CAP_LINKAT_TARGET, "lt" }, { CAP_MKDIRAT, "md" }, { CAP_MKFIFOAT, "mf" }, { CAP_MKNODAT, "mn" }, { CAP_RENAMEAT_SOURCE, "rs" }, { CAP_RENAMEAT_TARGET, "rt" }, { CAP_SYMLINKAT, "sl" }, { CAP_UNLINKAT, "un" }, /* Lookups - used to constrain *at() calls. */ { CAP_LOOKUP, "lo" }, /* Extended attributes. */ { CAP_EXTATTR_GET, "eg" }, { CAP_EXTATTR_SET, "es" }, { CAP_EXTATTR_DELETE, "ed" }, { CAP_EXTATTR_LIST, "el" }, /* Access Control Lists. */ { CAP_ACL_GET, "ag" }, { CAP_ACL_SET, "as" }, { CAP_ACL_DELETE, "ad" }, { CAP_ACL_CHECK, "ac" }, /* Socket operations. */ { CAP_ACCEPT, "at" }, { CAP_BIND, "bd" }, { CAP_CONNECT, "co" }, { CAP_GETPEERNAME, "pn" }, { CAP_GETSOCKNAME, "sn" }, { CAP_GETSOCKOPT, "gs" }, { CAP_LISTEN, "ln" }, { CAP_PEELOFF, "pf" }, { CAP_SETSOCKOPT, "ss" }, { CAP_SHUTDOWN, "sh" }, /* Mandatory Access Control. */ { CAP_MAC_GET, "mg" }, { CAP_MAC_SET, "ms" }, /* Methods on semaphores. */ { CAP_SEM_GETVALUE, "sg" }, { CAP_SEM_POST, "sp" }, { CAP_SEM_WAIT, "sw" }, /* Event monitoring and posting. */ { CAP_EVENT, "ev" }, { CAP_KQUEUE_EVENT, "ke" }, { CAP_KQUEUE_CHANGE, "kc" }, /* Strange and powerful rights that should not be given lightly. */ { CAP_IOCTL, "io" }, { CAP_TTYHOOK, "ty" }, /* Process management via process descriptors. */ { CAP_PDGETPID, "pg" }, { CAP_PDWAIT, "pw" }, { CAP_PDKILL, "pk" }, /* * Rights that allow to use bindat(2) and connectat(2) syscalls on a * directory descriptor. */ { CAP_BINDAT, "ba" }, { CAP_CONNECTAT, "ca" }, /* Aliases and defines that combine multiple rights. */ { CAP_PREAD, "prd" }, { CAP_PWRITE, "pwr" }, { CAP_MMAP_R, "mmr" }, { CAP_MMAP_W, "mmw" }, { CAP_MMAP_X, "mmx" }, { CAP_MMAP_RW, "mrw" }, { CAP_MMAP_RX, "mrx" }, { CAP_MMAP_WX, "mwx" }, { CAP_MMAP_RWX, "mma" }, { CAP_RECV, "re" }, { CAP_SEND, "sd" }, { CAP_SOCK_CLIENT, "scl" }, { CAP_SOCK_SERVER, "ssr" }, }; static const u_int cap_desc_count = nitems(cap_desc); static u_int width_capability(cap_rights_t *rightsp) { u_int count, i, width; count = 0; width = 0; for (i = 0; i < cap_desc_count; i++) { if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) { width += strlen(cap_desc[i].cd_desc); if (count) width++; count++; } } return (width); } static void print_capability(cap_rights_t *rightsp, u_int capwidth) { u_int count, i, width; count = 0; width = 0; for (i = width_capability(rightsp); i < capwidth; i++) { if (i != 0) xo_emit(" "); else 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)) { 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 procstat_files(struct procstat *procstat, struct kinfo_proc *kipp) { struct sockstat sock; struct filestat_list *head; struct filestat *fst; const char *str; 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 * of the widest capability string. Even if we get no processes * back, we will print the header, so we defer aborting due to a lack * of processes until after the header logic. */ capwidth = 0; head = procstat_getfiles(procstat, kipp, 0); if (head != NULL && (procstat_opts & PS_OPT_CAPABILITIES) != 0) { STAILQ_FOREACH(fst, head, next) { width = width_capability(&fst->fs_cap_rights); if (width > capwidth) capwidth = width; } if (capwidth < strlen("CAPABILITIES")) capwidth = strlen("CAPABILITIES"); } if ((procstat_opts & PS_OPT_NOHEADER) == 0) { if ((procstat_opts & PS_OPT_CAPABILITIES) != 0) xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s " "%-3s %-12s}\n", "PID", "COMM", "FD", "T", "FLAGS", capwidth, "CAPABILITIES", "PRO", "NAME"); else 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) { 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) xo_emit("{P: }{:fd/%s} ", "ctty"); else if (fst->fs_uflags & PS_FST_UFLAG_CDIR) xo_emit("{P: }{:fd/%s} ", "cwd"); else if (fst->fs_uflags & PS_FST_UFLAG_JAIL) xo_emit("{P: }{:fd/%s} ", "jail"); else if (fst->fs_uflags & PS_FST_UFLAG_RDIR) xo_emit("{P: }{:fd/%s} ", "root"); else if (fst->fs_uflags & PS_FST_UFLAG_TEXT) xo_emit("{P: }{:fd/%s} ", "text"); else if (fst->fs_uflags & PS_FST_UFLAG_TRACE) xo_emit("{:fd/%s} ", "trace"); else 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_PROCDESC: str = "P"; xo_emit("{eq:fd_type/procdesc}"); break; case PS_FST_TYPE_DEV: str = "D"; xo_emit("{eq:fd_type/dev}"); 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; } xo_emit("{d:fd_type/%1s/%s} ", str); if ((procstat_opts & PS_OPT_CAPABILITIES) == 0) { str = "-"; if (fst->fs_type == PS_FST_TYPE_VNODE) { error = procstat_get_vnode_info(procstat, fst, &vn, NULL); 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; } } xo_emit("{d:vnode_type/%1s/%s} ", str); } 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 ((procstat_opts & PS_OPT_CAPABILITIES) == 0) { if (fst->fs_ref_count > -1) xo_emit("{:ref_count/%3d/%d} ", fst->fs_ref_count); else xo_emit("{q:ref_count/%3c/%c} ", '-'); if (fst->fs_offset > -1) xo_emit("{:offset/%7jd/%jd} ", (intmax_t)fst->fs_offset); else xo_emit("{q:offset/%7c/%c} ", '-'); } if ((procstat_opts & PS_OPT_CAPABILITIES) != 0) { print_capability(&fst->fs_cap_rights, capwidth); xo_emit(" "); } switch (fst->fs_type) { case PS_FST_TYPE_SOCKET: error = procstat_get_socket_info(procstat, fst, &sock, NULL); if (error != 0) break; xo_emit("{:protocol/%-3s/%s} ", protocol_to_string(sock.dom_family, sock.type, sock.proto)); if (sock.proto == IPPROTO_TCP || sock.proto == IPPROTO_SCTP || sock.type == SOCK_STREAM) { xo_emit("{:sendq/%u} ", sock.sendq); xo_emit("{:recvq/%u} ", sock.recvq); } /* * While generally we like to print two addresses, * local and peer, for sockets, it turns out to be * more useful to print the first non-nul address for * local sockets, as typically they aren't bound and * connected, and the path strings can get long. */ if (sock.dom_family == AF_LOCAL) { struct sockaddr_un *sun = (struct sockaddr_un *)&sock.sa_local; if (sun->sun_path[0] != 0) addr_to_string(&sock.sa_local, src_addr, sizeof(src_addr)); else addr_to_string(&sock.sa_peer, src_addr, sizeof(src_addr)); xo_emit("{:path/%s}", src_addr); } else { 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: xo_emit("{:protocol/%-3s/%s} ", "-"); xo_emit("{:path/%-18s/%s}", fst->fs_path != NULL ? fst->fs_path : "-"); } xo_emit("\n"); xo_close_instance("files"); } xo_close_list("files"); procstat_freefiles(procstat, head); } Index: head/usr.bin/procstat/procstat_kstack.c =================================================================== --- head/usr.bin/procstat/procstat_kstack.c (revision 366209) +++ head/usr.bin/procstat/procstat_kstack.c (revision 366210) @@ -1,249 +1,250 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "procstat.h" /* * Walk the stack trace provided by the kernel and reduce it to what we * actually want to print. This involves stripping true instruction pointers, * frame numbers, and carriage returns as generated by stack(9). If -kk is * specified, print the function and offset, otherwise just the function. */ enum trace_state { TS_FRAMENUM, TS_PC, TS_AT, TS_FUNC, TS_OFF }; static enum trace_state kstack_nextstate(enum trace_state ts) { switch (ts) { case TS_FRAMENUM: return (TS_PC); case TS_PC: return (TS_AT); case TS_AT: return (TS_FUNC); case TS_FUNC: return (TS_OFF); case TS_OFF: return (TS_FRAMENUM); default: errx(-1, "kstack_nextstate"); } } static void kstack_cleanup(const char *old, char *new, int kflag) { enum trace_state old_ts, ts; const char *cp_old; char *cp_new; ts = TS_FRAMENUM; for (cp_old = old, cp_new = new; *cp_old != '\0'; cp_old++) { switch (*cp_old) { case ' ': case '\n': case '+': old_ts = ts; ts = kstack_nextstate(old_ts); if (old_ts == TS_OFF) { *cp_new = ' '; cp_new++; } if (kflag > 1 && old_ts == TS_FUNC) { *cp_new = '+'; cp_new++; } continue; } if (ts == TS_FUNC || (kflag > 1 && ts == TS_OFF)) { *cp_new = *cp_old; cp_new++; } } *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_new = '\0'; 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); } free(cp_tofree); } /* * Sort threads by tid. */ static int kinfo_kstack_compare(const void *a, const void *b) { return ((const struct kinfo_kstack *)a)->kkst_tid - ((const struct kinfo_kstack *)b)->kkst_tid; } static void kinfo_kstack_sort(struct kinfo_kstack *kkstp, int count) { qsort(kkstp, count, sizeof(*kkstp), kinfo_kstack_compare); } void procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_kstack *kkstp, *kkstp_free; struct kinfo_proc *kip, *kip_free; char trace[KKST_MAXLEN], encoded_trace[KKST_MAXLEN]; unsigned int i, j; unsigned int kip_count, kstk_count; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %6s %-19s %-19s %-29s}\n", "PID", "TID", "COMM", "TDNAME", "KSTACK"); kkstp = kkstp_free = procstat_getkstack(procstat, kipp, &kstk_count); if (kkstp == NULL) return; /* * We need to re-query for thread information, so don't use *kipp. */ kip = kip_free = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &kip_count); if (kip == NULL) { procstat_freekstack(procstat, kkstp_free); return; } kinfo_kstack_sort(kkstp, kstk_count); for (i = 0; i < kstk_count; i++) { kkstp = &kkstp_free[i]; /* * Look up the specific thread using its tid so we can * display the per-thread command line. */ kipp = NULL; for (j = 0; j < kip_count; j++) { kipp = &kip_free[j]; if (kkstp->kkst_tid == kipp->ki_tid) break; } if (kipp == NULL) continue; xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid); xo_emit("{:thread_id/%6d/%d} ", kkstp->kkst_tid); xo_emit("{:command/%-19s/%s} ", kipp->ki_comm); xo_emit("{:thread_name/%-19s/%s} ", kinfo_proc_thread_name(kipp)); switch (kkstp->kkst_state) { case KKST_STATE_RUNNING: xo_emit("{:state/%-29s/%s}\n", ""); continue; case KKST_STATE_SWAPPED: xo_emit("{:state/%-29s/%s}\n", ""); continue; case KKST_STATE_STACKOK: break; default: xo_emit("{:state/%-29s/%s}\n", ""); continue; } /* * The kernel generates a trace with carriage returns between * entries, but for a more compact view, we convert carriage * returns to spaces. */ kstack_cleanup(kkstp->kkst_trace, trace, (procstat_opts & PS_OPT_VERBOSE) != 0 ? 2 : 1); xo_open_list("trace"); kstack_cleanup_encoded(kkstp->kkst_trace, encoded_trace, (procstat_opts & PS_OPT_VERBOSE) != 0 ? 2 : 1); xo_close_list("trace"); xo_emit("{d:trace/%-29s}\n", trace); } procstat_freekstack(procstat, kkstp_free); procstat_freeprocs(procstat, kip_free); } Index: head/usr.bin/procstat/procstat_ptlwpinfo.c =================================================================== --- head/usr.bin/procstat/procstat_ptlwpinfo.c (revision 366209) +++ head/usr.bin/procstat/procstat_ptlwpinfo.c (revision 366210) @@ -1,95 +1,95 @@ /*- * Copyright (c) 2017 Dell EMC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ - #include - __FBSDID("$FreeBSD$"); + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include "procstat.h" void procstat_ptlwpinfo(struct procstat *prstat, struct kinfo_proc *kipp __unused) { struct ptrace_lwpinfo *pl; unsigned int count, i; pl = procstat_getptlwpinfo(prstat, &count); if (pl == NULL) return; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit( "{T:/%6s %7s %5s %5s %5s %6s %5s} {[:/%d}{T:/%s}{]:} {T:/%s}\n", "LWPID", "EVENT", "SIGNO", "CODE", "ERRNO", "PID", "UID", 2 * sizeof(void *) + 2, "ADDR", "TDNAME"); xo_open_container("threads"); for (i = 0; i < count; i++) { xo_open_container("thread"); xo_emit("{:lwpid/%6d} ", pl[i].pl_lwpid); switch (pl[i].pl_event) { case PL_EVENT_NONE: xo_emit("{eq:event/none}{d:event/%7s} ", "none"); break; case PL_EVENT_SIGNAL: xo_emit("{eq:event/signal}{d:event/%7s} ", "signal"); break; default: xo_emit("{eq:event/unknown}{d:event/%7s} ", "?"); break; } if ((pl[i].pl_flags & PL_FLAG_SI) != 0) { siginfo_t *si; si = &pl[i].pl_siginfo; xo_emit("{:signal_number/%5d} ", si->si_signo); xo_emit("{:code/%5d} ", si->si_code); xo_emit("{:signal_errno/%5d} ", si->si_errno); xo_emit("{:process_id/%6d} ", si->si_pid); xo_emit("{:user_id/%5d} ", si->si_uid); xo_emit("{[:/%d}{:address/%p}{]:} ", 2 * sizeof(void *) + 2, si->si_addr); } else { xo_emit("{:signal_number/%5s} ", "-"); xo_emit("{:code/%5s} ", "-"); xo_emit("{:signal_errno/%5s} ", "-"); xo_emit("{:process_id/%6s} ", "-"); xo_emit("{:user_id/%5s} ", "-"); xo_emit("{[:/%d}{:address/%s}{]:} ", 2 * sizeof(void *) + 2, "-"); } xo_emit("{:tdname/%s}\n", pl[i].pl_tdname); xo_close_container("thread"); } xo_close_container("threads"); procstat_freeptlwpinfo(prstat, pl); } Index: head/usr.bin/procstat/procstat_rlimit.c =================================================================== --- head/usr.bin/procstat/procstat_rlimit.c (revision 366209) +++ head/usr.bin/procstat/procstat_rlimit.c (revision 366210) @@ -1,129 +1,130 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Mikolaj Golub * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "procstat.h" static struct { const char *name; const char *suffix; } rlimit_param[15] = { {"cputime", "sec"}, {"filesize", "B "}, {"datasize", "B "}, {"stacksize", "B "}, {"coredumpsize", "B "}, {"memoryuse", "B "}, {"memorylocked", "B "}, {"maxprocesses", " "}, {"openfiles", " "}, {"sbsize", "B "}, {"vmemoryuse", "B "}, {"pseudo-terminals", " "}, {"swapuse", "B "}, {"kqueues", " "}, {"umtxp", " "}, }; #if RLIM_NLIMITS > 15 #error "Resource limits have grown. Add new entries to rlimit_param[]." #endif static const char * humanize_rlimit(int indx, rlim_t limit) { static char buf[14]; int scale; if (limit == RLIM_INFINITY) return ("infinity "); scale = humanize_number(buf, sizeof(buf) - 1, (int64_t)limit, rlimit_param[indx].suffix, HN_AUTOSCALE | HN_GETSCALE, HN_DECIMAL); (void)humanize_number(buf, sizeof(buf) - 1, (int64_t)limit, rlimit_param[indx].suffix, HN_AUTOSCALE, HN_DECIMAL); /* Pad with one space if there is no suffix prefix. */ if (scale == 0) sprintf(buf + strlen(buf), " "); return (buf); } void procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp) { struct rlimit rlimit; int i; if ((procstat_opts & PS_OPT_NOHEADER) == 0) { 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; xo_emit("{dk:process_id/%5d} {d:command/%-16s} " "{d:rlimit_param/%-16s} ", kipp->ki_pid, kipp->ki_comm, rlimit_param[i].name); 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)); } } Index: head/usr.bin/procstat/procstat_sigs.c =================================================================== --- head/usr.bin/procstat/procstat_sigs.c (revision 366209) +++ head/usr.bin/procstat/procstat_sigs.c (revision 366210) @@ -1,246 +1,247 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2010 Konstantin Belousov * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "procstat.h" static void procstat_print_signame(int sig) { char name[12]; int i; if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) { strlcpy(name, sys_signame[sig], sizeof(name)); for (i = 0; name[i] != 0; i++) name[i] = toupper(name[i]); 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 ((procstat_opts & PS_OPT_SIGNUM) == 0 && 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 { snprintf(name, 12, "%d", sig); xo_close_container(name); } } static void procstat_print_sig(const sigset_t *set, int sig, char 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; if ((procstat_opts & PS_OPT_NOHEADER) == 0) 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++) { xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid); xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm); procstat_print_signame(j); 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'); 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; int j; unsigned int count, i; char *threadid; if ((procstat_opts & PS_OPT_NOHEADER) == 0) 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, 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++) { 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); xo_emit(" "); procstat_print_sig(&kipp->ki_siglist, j, 'P'); procstat_print_sig(&kipp->ki_sigmask, j, 'B'); 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); } void procstat_sigfastblock(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_proc *kip; char *threadid; uintptr_t sigfastblk_addr; int error, name[4]; unsigned int count, i; size_t len; bool has_sigfastblk_addr; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %6s %-16s %-16s}\n", "PID", "TID", "COMM", "SIGFBLK"); kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, 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]; len = sizeof(sigfastblk_addr); name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_SIGFASTBLK; name[3] = kipp->ki_tid; error = sysctl(name, 4, &sigfastblk_addr, &len, NULL, 0); if (error < 0) { if (errno != ESRCH && errno != ENOTTY) { warn("sysctl: kern.proc.fastsigblk: %d", kipp->ki_tid); } has_sigfastblk_addr = false; } else has_sigfastblk_addr = true; asprintf(&threadid, "%d", kipp->ki_tid); if (threadid == NULL) xo_errc(1, ENOMEM, "Failed to allocate memory in " "procstat_sigfastblock()"); xo_open_container(threadid); 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); xo_emit("{e:sigfastblock/%#-16jx/%#jx}", has_sigfastblk_addr ? (uintmax_t)sigfastblk_addr : (uintmax_t)-1); xo_emit("{d:sigfastblock/%#-16jx/%#jx}", has_sigfastblk_addr ? (uintmax_t)sigfastblk_addr : (uintmax_t)-1); xo_emit("\n"); xo_close_container(threadid); free(threadid); } xo_close_container("threads"); procstat_freeprocs(procstat, kip); } Index: head/usr.bin/procstat/procstat_threads.c =================================================================== --- head/usr.bin/procstat/procstat_threads.c (revision 366209) +++ head/usr.bin/procstat/procstat_threads.c (revision 366210) @@ -1,135 +1,136 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "procstat.h" void procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_proc *kip; unsigned int count, i; const char *str; char *threadid; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %6s %-19s %-19s %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) return; 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()"); 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/%-19s/%s} ", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); xo_emit("{:thread_name/%-19s/%s} ", kinfo_proc_thread_name(kipp)); if (kipp->ki_oncpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu); else if (kipp->ki_lastcpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu); else xo_emit("{:cpu/%3s/%s} ", "-"); xo_emit("{:priority/%4d/%d} ", kipp->ki_pri.pri_level); switch (kipp->ki_stat) { case SRUN: str = "run"; break; case SSTOP: str = "stop"; break; case SSLEEP: str = "sleep"; break; case SLOCK: str = "lock"; break; case SWAIT: str = "wait"; break; case SZOMB: str = "zomb"; break; case SIDL: str = "idle"; break; default: str = "??"; break; } xo_emit("{:run_state/%-7s/%s} ", str); if (kipp->ki_kiflag & KI_LOCKBLOCK) { xo_emit("{:lock_name/*%-8s/%s} ", strlen(kipp->ki_lockname) ? kipp->ki_lockname : "-"); } else { xo_emit("{:wait_channel/%-9s/%s} ", strlen(kipp->ki_wmesg) ? kipp->ki_wmesg : "-"); } xo_close_container(threadid); free(threadid); xo_emit("\n"); } xo_close_container("threads"); procstat_freeprocs(procstat, kip); } Index: head/usr.bin/procstat/procstat_vm.c =================================================================== --- head/usr.bin/procstat/procstat_vm.c (revision 366209) +++ head/usr.bin/procstat/procstat_vm.c (revision 366210) @@ -1,170 +1,171 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2007 Robert N. M. Watson * Copyright (c) 2015 Allan Jude * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "procstat.h" void procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_vmentry *freep, *kve; int ptrwidth; int i, cnt; const char *str, *lstr; ptrwidth = 2*sizeof(void *) + 2; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %*s %*s %3s %4s %4s %3s %3s %-5s %-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]; 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_emit("{d:wired/%-1s} ", kve->kve_flags & KVME_FLAG_USER_WIRED ? "W" : "-"); 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_emit("{en:wired/%s}", kve->kve_flags & KVME_FLAG_USER_WIRED ? "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; } 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); }