PageRenderTime 27ms CodeModel.GetById 15ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/usr.bin/procstat/procstat.c

https://bitbucket.org/freebsd/freebsd-head/
C | 279 lines | 203 code | 40 blank | 36 comment | 64 complexity | 68ce9ebd6f8bf014e5639e57a92daac2 MD5 | raw file
  1/*-
  2 * Copyright (c) 2007, 2011 Robert N. M. Watson
  3 * All rights reserved.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions
  7 * are met:
  8 * 1. Redistributions of source code must retain the above copyright
  9 *    notice, this list of conditions and the following disclaimer.
 10 * 2. Redistributions in binary form must reproduce the above copyright
 11 *    notice, this list of conditions and the following disclaimer in the
 12 *    documentation and/or other materials provided with the distribution.
 13 *
 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 24 * SUCH DAMAGE.
 25 *
 26 * $FreeBSD$
 27 */
 28
 29#include <sys/param.h>
 30#include <sys/sysctl.h>
 31#include <sys/user.h>
 32
 33#include <err.h>
 34#include <libprocstat.h>
 35#include <stdio.h>
 36#include <stdlib.h>
 37#include <sysexits.h>
 38#include <unistd.h>
 39
 40#include "procstat.h"
 41
 42static int aflag, bflag, cflag, eflag, fflag, iflag, jflag, kflag, lflag, sflag;
 43static int tflag, vflag, xflag;
 44int	hflag, nflag, Cflag;
 45
 46static void
 47usage(void)
 48{
 49
 50	fprintf(stderr, "usage: procstat [-h] [-C] [-M core] [-N system] "
 51	    "[-w interval] \n");
 52	fprintf(stderr, "                [-b | -c | -e | -f | -i | -j | -k | "
 53	    "-l | -s | -t | -v | -x] [-a | pid ...]\n");
 54	exit(EX_USAGE);
 55}
 56
 57static void
 58procstat(struct procstat *prstat, struct kinfo_proc *kipp)
 59{
 60
 61	if (bflag)
 62		procstat_bin(kipp);
 63	else if (cflag)
 64		procstat_args(kipp);
 65	else if (eflag)
 66		procstat_env(kipp);
 67	else if (fflag)
 68		procstat_files(prstat, kipp);
 69	else if (iflag)
 70		procstat_sigs(prstat, kipp);
 71	else if (jflag)
 72		procstat_threads_sigs(prstat, kipp);
 73	else if (kflag)
 74		procstat_kstack(kipp, kflag);
 75	else if (lflag)
 76		procstat_rlimit(kipp);
 77	else if (sflag)
 78		procstat_cred(kipp);
 79	else if (tflag)
 80		procstat_threads(kipp);
 81	else if (vflag)
 82		procstat_vm(kipp);
 83	else if (xflag)
 84		procstat_auxv(kipp);
 85	else
 86		procstat_basic(kipp);
 87}
 88
 89/*
 90 * Sort processes first by pid and then tid.
 91 */
 92static int
 93kinfo_proc_compare(const void *a, const void *b)
 94{
 95	int i;
 96
 97	i = ((const struct kinfo_proc *)a)->ki_pid -
 98	    ((const struct kinfo_proc *)b)->ki_pid;
 99	if (i != 0)
100		return (i);
101	i = ((const struct kinfo_proc *)a)->ki_tid -
102	    ((const struct kinfo_proc *)b)->ki_tid;
103	return (i);
104}
105
106void
107kinfo_proc_sort(struct kinfo_proc *kipp, int count)
108{
109
110	qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare);
111}
112
113int
114main(int argc, char *argv[])
115{
116	int ch, interval, tmp;
117	int i;
118	struct kinfo_proc *p;
119	struct procstat *prstat;
120	long l;
121	pid_t pid;
122	char *dummy;
123	char *nlistf, *memf;
124	int cnt;
125
126	interval = 0;
127	memf = nlistf = NULL;
128	while ((ch = getopt(argc, argv, "CN:M:abcefijklhstvw:x")) != -1) {
129		switch (ch) {
130		case 'C':
131			Cflag++;
132			break;
133
134		case 'M':
135			memf = optarg;
136			break;
137		case 'N':
138			nlistf = optarg;
139			break;
140		case 'a':
141			aflag++;
142			break;
143
144		case 'b':
145			bflag++;
146			break;
147
148		case 'c':
149			cflag++;
150			break;
151
152		case 'e':
153			eflag++;
154			break;
155
156		case 'f':
157			fflag++;
158			break;
159
160		case 'i':
161			iflag++;
162			break;
163
164		case 'j':
165			jflag++;
166			break;
167
168		case 'k':
169			kflag++;
170			break;
171
172		case 'l':
173			lflag++;
174			break;
175
176		case 'n':
177			nflag++;
178			break;
179
180		case 'h':
181			hflag++;
182			break;
183
184		case 's':
185			sflag++;
186			break;
187
188		case 't':
189			tflag++;
190			break;
191
192		case 'v':
193			vflag++;
194			break;
195
196		case 'w':
197			l = strtol(optarg, &dummy, 10);
198			if (*dummy != '\0')
199				usage();
200			if (l < 1 || l > INT_MAX)
201				usage();
202			interval = l;
203			break;
204
205		case 'x':
206			xflag++;
207			break;
208
209		case '?':
210		default:
211			usage();
212		}
213
214	}
215	argc -= optind;
216	argv += optind;
217
218	/* We require that either 0 or 1 mode flags be set. */
219	tmp = bflag + cflag + eflag + fflag + (kflag ? 1 : 0) + lflag + sflag +
220	    tflag + vflag + xflag;
221	if (!(tmp == 0 || tmp == 1))
222		usage();
223
224	/* We allow -k to be specified up to twice, but not more. */
225	if (kflag > 2)
226		usage();
227
228	/* Must specify either the -a flag or a list of pids. */
229	if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
230		usage();
231
232	/* Only allow -C with -f. */
233	if (Cflag && !fflag)
234		usage();
235
236	if (memf != NULL)
237		prstat = procstat_open_kvm(nlistf, memf);
238	else
239		prstat = procstat_open_sysctl();
240	if (prstat == NULL)
241		errx(1, "procstat_open()");
242	do {
243		if (aflag) {
244			p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
245			if (p == NULL)
246				errx(1, "procstat_getprocs()");
247			kinfo_proc_sort(p, cnt);
248			for (i = 0; i < cnt; i++) {
249				procstat(prstat, &p[i]);
250
251				/* Suppress header after first process. */
252				hflag = 1;
253			}
254			procstat_freeprocs(prstat, p);
255		}
256		for (i = 0; i < argc; i++) {
257			l = strtol(argv[i], &dummy, 10);
258			if (*dummy != '\0')
259				usage();
260			if (l < 0)
261				usage();
262			pid = l;
263
264			p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt);
265			if (p == NULL)
266				errx(1, "procstat_getprocs()");
267			if (cnt != 0)
268				procstat(prstat, p);
269			procstat_freeprocs(prstat, p);
270
271			/* Suppress header after first process. */
272			hflag = 1;
273		}
274		if (interval)
275			sleep(interval);
276	} while (interval);
277	procstat_close(prstat);
278	exit(0);
279}