2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2007, 2011 Robert N. M. Watson
5 * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
6 * Copyright (c) 2017 Dell EMC
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/param.h>
34 #include <sys/sysctl.h>
38 #include <libprocstat.h>
47 static int aflag, bflag, cflag, eflag, fflag, iflag, jflag, kflag;
48 static int lflag, Lflag, rflag, sflag, tflag, vflag, xflag, Sflag;
49 int hflag, nflag, Cflag, Hflag;
55 xo_error("usage: procstat [--libxo] [-CHhn] [-M core] "
56 "[-N system] [-w interval]\n"
57 " [-b | -c | -e | -f | -i | -j | -k | "
59 " -S | -t | -v | -x]\n"
60 " [-a | pid | core ...]\n");
66 procstat(struct procstat *prstat, struct kinfo_proc *kipp)
70 asprintf(&pidstr, "%d", kipp->ki_pid);
72 xo_errc(1, ENOMEM, "Failed to allocate memory in procstat()");
73 xo_open_container(pidstr);
76 procstat_bin(prstat, kipp);
78 procstat_args(prstat, kipp);
80 procstat_env(prstat, kipp);
82 procstat_files(prstat, kipp);
84 procstat_sigs(prstat, kipp);
86 procstat_threads_sigs(prstat, kipp);
88 procstat_kstack(prstat, kipp, kflag);
90 procstat_rlimit(prstat, kipp);
92 procstat_ptlwpinfo(prstat);
94 procstat_rusage(prstat, kipp);
96 procstat_cred(prstat, kipp);
98 procstat_threads(prstat, kipp);
100 procstat_vm(prstat, kipp);
102 procstat_auxv(prstat, kipp);
104 procstat_cs(prstat, kipp);
106 procstat_basic(kipp);
108 xo_close_container(pidstr);
113 * Sort processes first by pid and then tid.
116 kinfo_proc_compare(const void *a, const void *b)
120 i = ((const struct kinfo_proc *)a)->ki_pid -
121 ((const struct kinfo_proc *)b)->ki_pid;
124 i = ((const struct kinfo_proc *)a)->ki_tid -
125 ((const struct kinfo_proc *)b)->ki_tid;
130 kinfo_proc_sort(struct kinfo_proc *kipp, int count)
133 qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare);
137 kinfo_proc_thread_name(const struct kinfo_proc *kipp)
139 static char name[MAXCOMLEN+1];
141 strlcpy(name, kipp->ki_tdname, sizeof(name));
142 strlcat(name, kipp->ki_moretdname, sizeof(name));
143 if (name[0] == '\0' || strcmp(kipp->ki_comm, name) == 0) {
152 main(int argc, char *argv[])
154 int ch, interval, tmp;
156 struct kinfo_proc *p;
157 struct procstat *prstat, *cprstat;
162 const char *xocontainer;
166 memf = nlistf = NULL;
167 argc = xo_parse_args(argc, argv);
168 xocontainer = "basic";
170 while ((ch = getopt(argc, argv, "abCcefHhijklLM:N:nrSstvw:x")) != -1) {
196 xocontainer = "binary";
201 xocontainer = "arguments";
206 xocontainer = "environment";
211 xocontainer = "files";
216 xocontainer = "signals";
221 xocontainer = "thread_signals";
226 xocontainer = "kstack";
231 xocontainer = "rlimit";
236 xocontainer = "ptlwpinfo";
249 xocontainer = "rusage";
254 xocontainer = "credentials";
259 xocontainer = "threads";
268 l = strtol(optarg, &dummy, 10);
271 if (l < 1 || l > INT_MAX)
278 xocontainer = "auxv";
290 /* We require that either 0 or 1 mode flags be set. */
291 tmp = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) +
292 lflag + rflag + sflag + tflag + vflag + xflag + Sflag;
293 if (!(tmp == 0 || tmp == 1))
296 /* We allow -k to be specified up to twice, but not more. */
300 /* Must specify either the -a flag or a list of pids. */
301 if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
304 /* Only allow -C with -f. */
309 prstat = procstat_open_kvm(nlistf, memf);
311 prstat = procstat_open_sysctl();
313 xo_errx(1, "procstat_open()");
315 xo_set_version(PROCSTAT_XO_VERSION);
316 xo_open_container("procstat");
317 xo_open_container(xocontainer);
320 p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
322 xo_errx(1, "procstat_getprocs()");
323 kinfo_proc_sort(p, cnt);
324 for (i = 0; i < cnt; i++) {
325 procstat(prstat, &p[i]);
327 /* Suppress header after first process. */
331 procstat_freeprocs(prstat, p);
333 for (i = 0; i < argc; i++) {
334 l = strtol(argv[i], &dummy, 10);
335 if (*dummy == '\0') {
340 p = procstat_getprocs(prstat, KERN_PROC_PID,
343 xo_errx(1, "procstat_getprocs()");
346 procstat_freeprocs(prstat, p);
348 cprstat = procstat_open_core(argv[i]);
349 if (cprstat == NULL) {
350 warnx("procstat_open()");
353 p = procstat_getprocs(cprstat, KERN_PROC_PID,
356 xo_errx(1, "procstat_getprocs()");
358 procstat(cprstat, p);
359 procstat_freeprocs(cprstat, p);
360 procstat_close(cprstat);
362 /* Suppress header after first process. */
366 xo_close_container(xocontainer);
367 xo_close_container("procstat");
373 procstat_close(prstat);