Add pargs, penv, pwdx commands and aliases to procstat(1).

Intent is to mimic Solaris commands with the same names.

Submitted by:	Juraj Lutter <juraj@lutter.sk>
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D26310
This commit is contained in:
kib 2020-09-18 12:59:27 +00:00
parent c6ab1f6e61
commit 6fcc8779c0
7 changed files with 360 additions and 97 deletions

View File

@ -13,15 +13,25 @@ SRCS= procstat.c \
procstat_cs.c \
procstat_files.c \
procstat_kstack.c \
procstat_penv.c \
procstat_ptlwpinfo.c \
procstat_pwdx.c \
procstat_rlimit.c \
procstat_rusage.c \
procstat_sigs.c \
procstat_threads.c \
procstat_vm.c
MLINKS+= procstat.1 pargs.1
MLINKS+= procstat.1 penv.1
MLINKS+= procstat.1 pwdx.1
LIBADD+= procstat xo util sbuf
LINKS+= ${BINDIR}/procstat ${BINDIR}/pargs
LINKS+= ${BINDIR}/procstat ${BINDIR}/penv
LINKS+= ${BINDIR}/procstat ${BINDIR}/pwdx
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 4, 2019
.Dd September 14, 2020
.Dt PROCSTAT 1
.Os
.Sh NAME
@ -102,6 +102,15 @@
.Op Fl N Ar system
.Op Fl w Ar interval
.Ar core ...
.Nm pargs
.Op Fl -libxo
.Ar pid ...
.Nm penv
.Op Fl -libxo
.Ar pid ...
.Nm pwdx
.Op Fl -libxo
.Ar pid ...
.Sh DESCRIPTION
.Nm
utility displays detailed information about the processes identified by the
@ -112,6 +121,17 @@ flag is used, all processes.
It can also display information extracted from a process core file, if
the core file is specified as the argument.
.Pp
The
.Nm pargs ,
.Nm penv
and
.Nm pwdx
utilities display the arguments, environment, and current working directory,
respectively of the process specified by
.Ar pid
argument.
They mimic the behavior of Solaris utilities of the same names.
.Pp
If the
.Fl -libxo
flag is specified the output is generated via
@ -121,7 +141,8 @@ See
.Xr xo_parse_args 3
for details on command line arguments.
.Pp
The following commands are available:
The following commands are available for
.Nm :
.Bl -tag -width indent
.It Ar basic
Print basic process statistics (this is the default).
@ -196,6 +217,12 @@ Display thread information for the process.
Display virtual memory mappings for the process.
.It Ar auxv | Fl x
Display ELF auxiliary vector for the process.
.It Ar pargs
Display arguments for the process.
.It Ar penv
Display environment variables for the process.
.It Ar pwdx
Display current working directory for the process.
.El
.Pp
All options generate output in the format of a table, the first field of
@ -430,7 +457,7 @@ process signal disposition details, three symbols
if signal is pending in the global process queue; - otherwise.
.It I
if signal delivery disposition is
.Dv SIG_IGN;
.Dv SIG_IGN ;
- otherwise.
.It C
if the signal will be caught; - otherwise.
@ -711,6 +738,10 @@ support was added by
.An -nosplit
Allan Jude
.Aq Mt allanjude@FreeBSD.org .
.br
.An Juraj Lutter
.Aq Mt juraj@lutter.sk
added the pargs, penv and pwdx functionality.
.Sh BUGS
The display of open file or memory mapping pathnames is implemented using the
kernel's name cache.

View File

@ -68,6 +68,23 @@ 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 },
@ -88,8 +105,14 @@ static const struct procstat_cmd cmd_table[] = {
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,
@ -106,43 +129,49 @@ static const struct procstat_cmd cmd_table[] = {
};
static void
usage(void)
usage(const struct procstat_cmd *cmd)
{
size_t i, l;
int multi;
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");
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);
@ -202,6 +231,25 @@ kinfo_proc_thread_name(const struct kinfo_proc *kipp)
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)
{
@ -237,17 +285,14 @@ getcmd(const char *str)
int
main(int argc, char *argv[])
{
int ch, interval;
int i;
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;
char *dummy;
char *nlistf, *memf;
int aflag;
int cnt;
int aflag, ch, cnt, i, interval;
interval = 0;
cmd = NULL;
@ -255,6 +300,9 @@ main(int argc, char *argv[])
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':
@ -262,7 +310,7 @@ main(int argc, char *argv[])
break;
case 'b':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("binary");
break;
case 'C':
@ -270,17 +318,17 @@ main(int argc, char *argv[])
break;
case 'c':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("arguments");
break;
case 'e':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("environment");
break;
case 'f':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("files");
break;
case 'H':
@ -291,33 +339,33 @@ main(int argc, char *argv[])
break;
case 'i':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("signals");
break;
case 'j':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("tsignals");
break;
case 'k':
if (cmd != NULL && cmd->cmd == procstat_kstack) {
if ((procstat_opts & PS_OPT_VERBOSE) != 0)
usage();
usage(cmd);
procstat_opts |= PS_OPT_VERBOSE;
} else {
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("kstack");
}
break;
case 'L':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("ptlwpinfo");
break;
case 'l':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("rlimit");
break;
case 'M':
@ -331,75 +379,79 @@ main(int argc, char *argv[])
break;
case 'r':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("rusage");
break;
case 'S':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("cpuset");
break;
case 's':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("credentials");
break;
case 't':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("threads");
break;
case 'v':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("vm");
break;
case 'w':
l = strtol(optarg, &dummy, 10);
if (*dummy != '\0')
usage();
usage(cmd);
if (l < 1 || l > INT_MAX)
usage();
usage(cmd);
interval = l;
break;
case 'x':
if (cmd != NULL)
usage();
usage(cmd);
cmd = getcmd("auxv");
break;
case '?':
default:
usage();
usage(cmd);
}
}
argc -= optind;
argv += optind;
if (cmd == NULL && argv[0] != NULL && (cmd = getcmd(argv[0])) != NULL) {
if (cmd == NULL && argv[0] != NULL)
cmd = getcmd(argv[0]);
if (cmd != NULL) {
if ((procstat_opts & PS_SUBCOMMAND_OPTS) != 0)
usage();
usage(cmd);
if (cmd->opt != NULL) {
optreset = 1;
optind = 1;
cmd->opt(argc, argv);
argc -= optind;
argv += optind;
if ((cmd->cmp & PS_MODE_COMPAT) == 0) {
argc -= optind;
argv += optind;
}
} else {
argc -= 1;
argv += 1;
}
} else {
if (cmd == NULL)
cmd = getcmd("basic");
if (cmd->cmd != procstat_files &&
(procstat_opts & PS_OPT_CAPABILITIES) != 0)
usage();
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();
usage(cmd);
if (memf != NULL)
prstat = procstat_open_kvm(nlistf, memf);
@ -408,9 +460,11 @@ main(int argc, char *argv[])
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("procstat");
xo_open_container(cmd->xocontainer);
xo_open_container(progname);
xo_open_container(xocontainer);
if (aflag) {
p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
@ -430,7 +484,7 @@ main(int argc, char *argv[])
l = strtol(argv[i], &dummy, 10);
if (*dummy == '\0') {
if (l < 0)
usage();
usage(cmd);
pid = l;
p = procstat_getprocs(prstat, KERN_PROC_PID,
@ -441,26 +495,34 @@ main(int argc, char *argv[])
procstat(cmd, prstat, p);
procstat_freeprocs(prstat, p);
} else {
cprstat = procstat_open_core(argv[i]);
if (cprstat == NULL) {
warnx("procstat_open()");
continue;
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);
}
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);
}
/* Suppress header after first process. */
procstat_opts |= PS_OPT_NOHEADER;
if ((cmd->cmp & PS_MODE_COMPAT) == 0) {
/* Suppress header after first process. */
procstat_opts |= PS_OPT_NOHEADER;
}
}
xo_close_container(cmd->xocontainer);
xo_close_container("procstat");
xo_close_container(xocontainer);
xo_close_container(progname);
xo_finish();
if (interval)
sleep(interval);
@ -480,7 +542,7 @@ cmdopt_none(int argc, char * const argv[])
switch (ch) {
case '?':
default:
usage();
usage(NULL);
}
}
}
@ -497,7 +559,7 @@ cmdopt_verbose(int argc, char * const argv[])
break;
case '?':
default:
usage();
usage(NULL);
}
}
}
@ -514,7 +576,7 @@ cmdopt_signals(int argc, char * const argv[])
break;
case '?':
default:
usage();
usage(NULL);
}
}
}
@ -533,7 +595,7 @@ cmdopt_rusage(int argc, char * const argv[])
break;
case '?':
default:
usage();
usage(NULL);
}
}
}
@ -550,7 +612,7 @@ cmdopt_files(int argc, char * const argv[])
break;
case '?':
default:
usage();
usage(NULL);
}
}
}

View File

@ -42,7 +42,8 @@ enum {
PS_OPT_NOHEADER = 0x02,
PS_OPT_PERTHREAD = 0x04,
PS_OPT_SIGNUM = 0x08,
PS_OPT_VERBOSE = 0x10
PS_OPT_VERBOSE = 0x10,
PS_MODE_COMPAT = 0x20,
};
#define PS_SUBCOMMAND_OPTS \
@ -64,7 +65,10 @@ void procstat_cs(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_env(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_files(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_kstack(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_pargs(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_penv(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_ptlwpinfo(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_pwdx(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_rusage(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_sigfastblock(struct procstat *procstat,

View File

@ -68,7 +68,7 @@ kstack_nextstate(enum trace_state ts)
return (TS_OFF);
case TS_OFF:
return TS_FRAMENUM;
return (TS_FRAMENUM);
default:
errx(-1, "kstack_nextstate");

View File

@ -0,0 +1,86 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2020 Juraj Lutter <juraj@lutter.sk>
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <err.h>
#include <errno.h>
#include <libprocstat.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "procstat.h"
void
procstat_pargs(struct procstat *procstat, struct kinfo_proc *kipp)
{
int i;
char **args;
args = procstat_getargv(procstat, kipp, 0);
xo_emit("{k:process_id/%d}: {:command/%s/%s}\n", kipp->ki_pid,
kipp->ki_comm);
if (args == NULL) {
xo_emit("{d:args/-}\n");
} else {
for (i = 0; args[i] != NULL; i++) {
xo_emit("{Ld:argv[}{Ld:/%d}{Ldwc:]}{l:argv/%s}\n",
i, args[i]);
}
}
}
void
procstat_penv(struct procstat *procstat, struct kinfo_proc *kipp)
{
int i;
char **envs;
envs = procstat_getenvv(procstat, kipp, 0);
xo_emit("{k:process_id/%d}: {:command/%s/%s}\n", kipp->ki_pid,
kipp->ki_comm);
if (envs == NULL) {
xo_emit("{d:env/-}\n");
} else {
for (i = 0; envs[i] != NULL; i++) {
xo_emit("{Ld:envp[}{Ld:/%d}{Ldwc:]}{l:envp/%s}\n",
i, envs[i]);
}
}
}

View File

@ -0,0 +1,70 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2020 Juraj Lutter <juraj@lutter.sk>
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/capsicum.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/un.h>
#include <sys/user.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <libprocstat.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "procstat.h"
void
procstat_pwdx(struct procstat *procstat, struct kinfo_proc *kipp)
{
struct filestat_list *head;
struct filestat *fst;
head = procstat_getfiles(procstat, kipp, 0);
if (head == NULL)
return;
STAILQ_FOREACH(fst, head, next) {
if ((fst->fs_uflags & PS_FST_UFLAG_CDIR) &&
(fst->fs_path != NULL)) {
xo_emit("{k:process_id/%d}{P:: }", kipp->ki_pid);
xo_emit("{:cwd/%s}", fst->fs_path);
xo_emit("\n");
}
}
procstat_freefiles(procstat, head);
}