xref: /freebsd/usr.sbin/pstat/pstat.c (revision eedc343625e28519e717a9867dff20efe5081a12)
1dea673e9SRodney W. Grimes /*-
29c5cdfe0SPeter Wemm  * Copyright (c) 1980, 1991, 1993, 1994
3dea673e9SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4dea673e9SRodney W. Grimes  *
5dea673e9SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
6dea673e9SRodney W. Grimes  * modification, are permitted provided that the following conditions
7dea673e9SRodney W. Grimes  * are met:
8dea673e9SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
9dea673e9SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
10dea673e9SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
11dea673e9SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
12dea673e9SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
13dea673e9SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
14dea673e9SRodney W. Grimes  *    must display the following acknowledgement:
15dea673e9SRodney W. Grimes  *	This product includes software developed by the University of
16dea673e9SRodney W. Grimes  *	California, Berkeley and its contributors.
17dea673e9SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
18dea673e9SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
19dea673e9SRodney W. Grimes  *    without specific prior written permission.
20dea673e9SRodney W. Grimes  *
21dea673e9SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22dea673e9SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23dea673e9SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24dea673e9SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25dea673e9SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26dea673e9SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27dea673e9SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28dea673e9SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29dea673e9SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30dea673e9SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31dea673e9SRodney W. Grimes  * SUCH DAMAGE.
32dea673e9SRodney W. Grimes  */
33dea673e9SRodney W. Grimes 
34dea673e9SRodney W. Grimes #ifndef lint
35d9961cfdSPhilippe Charnier static const char copyright[] =
369c5cdfe0SPeter Wemm "@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
37dea673e9SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
38dea673e9SRodney W. Grimes #endif /* not lint */
39dea673e9SRodney W. Grimes 
40dea673e9SRodney W. Grimes #ifndef lint
41d9961cfdSPhilippe Charnier #if 0
429c5cdfe0SPeter Wemm static char sccsid[] = "@(#)pstat.c	8.16 (Berkeley) 5/9/95";
43d9961cfdSPhilippe Charnier #endif
44d9961cfdSPhilippe Charnier static const char rcsid[] =
45eedc3436SMatthew Dillon 	"$Id: pstat.c,v 1.37 1998/08/19 01:32:28 bde Exp $";
46dea673e9SRodney W. Grimes #endif /* not lint */
47dea673e9SRodney W. Grimes 
48dea673e9SRodney W. Grimes #include <sys/param.h>
49dea673e9SRodney W. Grimes #include <sys/time.h>
50dea673e9SRodney W. Grimes #include <sys/vnode.h>
51dea673e9SRodney W. Grimes #include <sys/ucred.h>
52dea673e9SRodney W. Grimes #define KERNEL
53dea673e9SRodney W. Grimes #include <sys/file.h>
54dea673e9SRodney W. Grimes #include <ufs/ufs/quota.h>
55dea673e9SRodney W. Grimes #include <ufs/ufs/inode.h>
56dea673e9SRodney W. Grimes #include <sys/mount.h>
579c5cdfe0SPeter Wemm #include <sys/uio.h>
589c5cdfe0SPeter Wemm #include <sys/namei.h>
599c5cdfe0SPeter Wemm #include <miscfs/union/union.h>
60dea673e9SRodney W. Grimes #undef KERNEL
61dea673e9SRodney W. Grimes #include <sys/stat.h>
62a62dc406SDoug Rabson #include <nfs/rpcv2.h>
63a62dc406SDoug Rabson #include <nfs/nfsproto.h>
649c5cdfe0SPeter Wemm #include <nfs/nfs.h>
65dea673e9SRodney W. Grimes #include <nfs/nfsnode.h>
66dea673e9SRodney W. Grimes #include <sys/ioctl.h>
6790300419SAndrey A. Chernov #include <sys/ioctl_compat.h>	/* XXX NTTYDISC is too well hidden */
68dea673e9SRodney W. Grimes #include <sys/tty.h>
69dea673e9SRodney W. Grimes #include <sys/conf.h>
708d7547c2SDavid Greenman #include <sys/rlist.h>
71eedc3436SMatthew Dillon #include <sys/blist.h>
72dea673e9SRodney W. Grimes 
733aab05cfSPoul-Henning Kamp #include <sys/user.h>
74dea673e9SRodney W. Grimes #include <sys/sysctl.h>
75dea673e9SRodney W. Grimes 
76dea673e9SRodney W. Grimes #include <err.h>
775d98ce75SBruce Evans #include <fcntl.h>
78dea673e9SRodney W. Grimes #include <kvm.h>
79dea673e9SRodney W. Grimes #include <limits.h>
80dea673e9SRodney W. Grimes #include <nlist.h>
81dea673e9SRodney W. Grimes #include <stdio.h>
82dea673e9SRodney W. Grimes #include <stdlib.h>
83dea673e9SRodney W. Grimes #include <string.h>
84dea673e9SRodney W. Grimes #include <unistd.h>
85dea673e9SRodney W. Grimes 
86dea673e9SRodney W. Grimes struct nlist nl[] = {
878d7547c2SDavid Greenman #define VM_SWAPLIST	0
888d7547c2SDavid Greenman 	{ "_swaplist" },/* list of free swap areas */
89eedc3436SMatthew Dillon #define NLMANDATORYBEG	1
908d7547c2SDavid Greenman #define VM_SWDEVT	1
91dea673e9SRodney W. Grimes 	{ "_swdevt" },	/* list of swap devices and sizes */
92eedc3436SMatthew Dillon #define VM_NSWDEV	2
93dea673e9SRodney W. Grimes 	{ "_nswdev" },	/* number of swap devices */
94eedc3436SMatthew Dillon #define VM_DMMAX	3
95dea673e9SRodney W. Grimes 	{ "_dmmax" },	/* maximum size of a swap block */
96eedc3436SMatthew Dillon #define	V_MOUNTLIST	4
97dea673e9SRodney W. Grimes 	{ "_mountlist" },	/* address of head of mount list. */
98eedc3436SMatthew Dillon #define V_NUMV		5
99dea673e9SRodney W. Grimes 	{ "_numvnodes" },
100eedc3436SMatthew Dillon #define	FNL_NFILE	6
101dea673e9SRodney W. Grimes 	{"_nfiles"},
102eedc3436SMatthew Dillon #define FNL_MAXFILE	7
103dea673e9SRodney W. Grimes 	{"_maxfiles"},
104eedc3436SMatthew Dillon #define NLMANDATORYEND FNL_MAXFILE	/* names up to here are mandatory */
105eedc3436SMatthew Dillon #define	SCONS		NLMANDATORYEND + 1
106dea673e9SRodney W. Grimes 	{ "_cons" },
107eedc3436SMatthew Dillon #define	SPTY		NLMANDATORYEND + 2
108dea673e9SRodney W. Grimes 	{ "_pt_tty" },
109eedc3436SMatthew Dillon #define	SNPTY		NLMANDATORYEND + 3
110dea673e9SRodney W. Grimes 	{ "_npty" },
111eedc3436SMatthew Dillon #define	VM_SWAPBLIST	NLMANDATORYEND + 4
112eedc3436SMatthew Dillon 	{ "_swapblist" },
113dea673e9SRodney W. Grimes 
114dea673e9SRodney W. Grimes #ifdef hp300
115eedc3436SMatthew Dillon #define	SDCA	(VM_SWAPBLIST+1)
116dea673e9SRodney W. Grimes 	{ "_dca_tty" },
117eedc3436SMatthew Dillon #define	SNDCA	(VM_SWAPBLIST+2)
118dea673e9SRodney W. Grimes 	{ "_ndca" },
119eedc3436SMatthew Dillon #define	SDCM	(VM_SWAPBLIST+3)
120dea673e9SRodney W. Grimes 	{ "_dcm_tty" },
121eedc3436SMatthew Dillon #define	SNDCM	(VM_SWAPBLIST+4)
122dea673e9SRodney W. Grimes 	{ "_ndcm" },
123eedc3436SMatthew Dillon #define	SDCL	(VM_SWAPBLIST+5)
124dea673e9SRodney W. Grimes 	{ "_dcl_tty" },
125eedc3436SMatthew Dillon #define	SNDCL	(VM_SWAPBLIST+6)
126dea673e9SRodney W. Grimes 	{ "_ndcl" },
127eedc3436SMatthew Dillon #define	SITE	(VM_SWAPBLIST+7)
128dea673e9SRodney W. Grimes 	{ "_ite_tty" },
129eedc3436SMatthew Dillon #define	SNITE	(VM_SWAPBLIST+8)
130dea673e9SRodney W. Grimes 	{ "_nite" },
131dea673e9SRodney W. Grimes #endif
132dea673e9SRodney W. Grimes 
133dea673e9SRodney W. Grimes #ifdef mips
134eedc3436SMatthew Dillon #define SDC	(VM_SWAPBLIST+1)
135dea673e9SRodney W. Grimes 	{ "_dc_tty" },
136eedc3436SMatthew Dillon #define SNDC	(VM_SWAPBLIST+2)
137dea673e9SRodney W. Grimes 	{ "_dc_cnt" },
138dea673e9SRodney W. Grimes #endif
139dea673e9SRodney W. Grimes 
1405a3391bfSAndrey A. Chernov #ifdef __FreeBSD__
141eedc3436SMatthew Dillon #define SCCONS	(VM_SWAPBLIST+1)
142de4c8be3SSøren Schmidt 	{ "_sccons" },
143eedc3436SMatthew Dillon #define NSCCONS	(VM_SWAPBLIST+2)
144de4c8be3SSøren Schmidt 	{ "_nsccons" },
145eedc3436SMatthew Dillon #define SIO  (VM_SWAPBLIST+3)
14690300419SAndrey A. Chernov 	{ "_sio_tty" },
147eedc3436SMatthew Dillon #define NSIO (VM_SWAPBLIST+4)
14890300419SAndrey A. Chernov 	{ "_nsio_tty" },
149eedc3436SMatthew Dillon #define RC  (VM_SWAPBLIST+5)
15090300419SAndrey A. Chernov 	{ "_rc_tty" },
151eedc3436SMatthew Dillon #define NRC (VM_SWAPBLIST+6)
15290300419SAndrey A. Chernov 	{ "_nrc_tty" },
153eedc3436SMatthew Dillon #define CY  (VM_SWAPBLIST+7)
15424f769b0SBruce Evans 	{ "_cy_tty" },
155eedc3436SMatthew Dillon #define NCY (VM_SWAPBLIST+8)
15624f769b0SBruce Evans 	{ "_ncy_tty" },
157eedc3436SMatthew Dillon #define SI  (VM_SWAPBLIST+9)
158a9aa8c37SPeter Wemm 	{ "_si_tty" },
159eedc3436SMatthew Dillon #define NSI (VM_SWAPBLIST+10)
160a9aa8c37SPeter Wemm 	{ "_si_Nports" },
1615a3391bfSAndrey A. Chernov #endif
162dea673e9SRodney W. Grimes 	{ "" }
163dea673e9SRodney W. Grimes };
164dea673e9SRodney W. Grimes 
165dea673e9SRodney W. Grimes int	usenumflag;
166dea673e9SRodney W. Grimes int	totalflag;
167eedc3436SMatthew Dillon int	swapflag;
168dea673e9SRodney W. Grimes char	*nlistf	= NULL;
169dea673e9SRodney W. Grimes char	*memf	= NULL;
170dea673e9SRodney W. Grimes kvm_t	*kd;
171dea673e9SRodney W. Grimes 
172d9961cfdSPhilippe Charnier char	*usagestr;
17359392fe2SPoul-Henning Kamp 
1749c5cdfe0SPeter Wemm struct {
1759c5cdfe0SPeter Wemm 	int m_flag;
1769c5cdfe0SPeter Wemm 	const char *m_name;
1779c5cdfe0SPeter Wemm } mnt_flags[] = {
1789c5cdfe0SPeter Wemm 	{ MNT_RDONLY, "rdonly" },
1799c5cdfe0SPeter Wemm 	{ MNT_SYNCHRONOUS, "sync" },
1809c5cdfe0SPeter Wemm 	{ MNT_NOEXEC, "noexec" },
1819c5cdfe0SPeter Wemm 	{ MNT_NOSUID, "nosuid" },
1829c5cdfe0SPeter Wemm 	{ MNT_NODEV, "nodev" },
1839c5cdfe0SPeter Wemm 	{ MNT_UNION, "union" },
1849c5cdfe0SPeter Wemm 	{ MNT_ASYNC, "async" },
18595cddebbSPeter Wemm 	{ MNT_NOATIME, "noatime" },
1869c5cdfe0SPeter Wemm 	{ MNT_EXRDONLY, "exrdonly" },
1879c5cdfe0SPeter Wemm 	{ MNT_EXPORTED, "exported" },
1889c5cdfe0SPeter Wemm 	{ MNT_DEFEXPORTED, "defexported" },
1899c5cdfe0SPeter Wemm 	{ MNT_EXPORTANON, "exportanon" },
1909c5cdfe0SPeter Wemm 	{ MNT_EXKERB, "exkerb" },
1919c5cdfe0SPeter Wemm 	{ MNT_LOCAL, "local" },
1929c5cdfe0SPeter Wemm 	{ MNT_QUOTA, "quota" },
1939c5cdfe0SPeter Wemm 	{ MNT_ROOTFS, "rootfs" },
19495cddebbSPeter Wemm 	{ MNT_USER, "user" },
1959c5cdfe0SPeter Wemm 	{ MNT_UPDATE, "update" },
1969c5cdfe0SPeter Wemm 	{ MNT_DELEXPORT },
1979c5cdfe0SPeter Wemm 	{ MNT_UPDATE, "update" },
1989c5cdfe0SPeter Wemm 	{ MNT_DELEXPORT, "delexport" },
1999c5cdfe0SPeter Wemm 	{ MNT_RELOAD, "reload" },
2009c5cdfe0SPeter Wemm 	{ MNT_FORCE, "force" },
201b1f4a44bSJulian Elischer #if 0
2029c5cdfe0SPeter Wemm 	{ MNT_UNMOUNT, "unmount" },
20395cddebbSPeter Wemm 	{ MNT_MWAIT, "mwait" },
2049c5cdfe0SPeter Wemm 	{ MNT_WANTRDWR, "wantrdwr" },
205b1f4a44bSJulian Elischer #endif
2069c5cdfe0SPeter Wemm 	{ 0 }
2079c5cdfe0SPeter Wemm };
2089c5cdfe0SPeter Wemm 
2099c5cdfe0SPeter Wemm 
210dea673e9SRodney W. Grimes #define	SVAR(var) __STRING(var)	/* to force expansion */
211dea673e9SRodney W. Grimes #define	KGET(idx, var)							\
212dea673e9SRodney W. Grimes 	KGET1(idx, &var, sizeof(var), SVAR(var))
213dea673e9SRodney W. Grimes #define	KGET1(idx, p, s, msg)						\
214dea673e9SRodney W. Grimes 	KGET2(nl[idx].n_value, p, s, msg)
215dea673e9SRodney W. Grimes #define	KGET2(addr, p, s, msg)						\
216dea673e9SRodney W. Grimes 	if (kvm_read(kd, (u_long)(addr), p, s) != s)			\
217dea673e9SRodney W. Grimes 		warnx("cannot read %s: %s", msg, kvm_geterr(kd))
218eedc3436SMatthew Dillon #define	KGETN(idx, var)							\
219eedc3436SMatthew Dillon 	KGET1N(idx, &var, sizeof(var), SVAR(var))
220eedc3436SMatthew Dillon #define	KGET1N(idx, p, s, msg)						\
221eedc3436SMatthew Dillon 	KGET2N(nl[idx].n_value, p, s, msg)
222eedc3436SMatthew Dillon #define	KGET2N(addr, p, s, msg)						\
223eedc3436SMatthew Dillon 	((kvm_read(kd, (u_long)(addr), p, s) == s) ? 1 : 0)
224dea673e9SRodney W. Grimes #define	KGETRET(addr, p, s, msg)					\
225dea673e9SRodney W. Grimes 	if (kvm_read(kd, (u_long)(addr), p, s) != s) {			\
226dea673e9SRodney W. Grimes 		warnx("cannot read %s: %s", msg, kvm_geterr(kd));	\
227dea673e9SRodney W. Grimes 		return (0);						\
228dea673e9SRodney W. Grimes 	}
229dea673e9SRodney W. Grimes 
230dea673e9SRodney W. Grimes void	filemode __P((void));
231dea673e9SRodney W. Grimes int	getfiles __P((char **, int *));
232dea673e9SRodney W. Grimes struct mount *
233dea673e9SRodney W. Grimes 	getmnt __P((struct mount *));
234dea673e9SRodney W. Grimes struct e_vnode *
235dea673e9SRodney W. Grimes 	kinfo_vnodes __P((int *));
236dea673e9SRodney W. Grimes struct e_vnode *
237dea673e9SRodney W. Grimes 	loadvnodes __P((int *));
238dea673e9SRodney W. Grimes void	mount_print __P((struct mount *));
239dea673e9SRodney W. Grimes void	nfs_header __P((void));
240dea673e9SRodney W. Grimes int	nfs_print __P((struct vnode *));
241dea673e9SRodney W. Grimes void	swapmode __P((void));
242dea673e9SRodney W. Grimes void	ttymode __P((void));
243dea673e9SRodney W. Grimes void	ttyprt __P((struct tty *, int));
244a9aa8c37SPeter Wemm void	ttytype __P((struct tty *, char *, int, int, int));
245dea673e9SRodney W. Grimes void	ufs_header __P((void));
246dea673e9SRodney W. Grimes int	ufs_print __P((struct vnode *));
2479c5cdfe0SPeter Wemm void	union_header __P((void));
2489c5cdfe0SPeter Wemm int	union_print __P((struct vnode *));
249d9961cfdSPhilippe Charnier static void usage __P((void));
250dea673e9SRodney W. Grimes void	vnode_header __P((void));
251dea673e9SRodney W. Grimes void	vnode_print __P((struct vnode *, struct vnode *));
252dea673e9SRodney W. Grimes void	vnodemode __P((void));
253dea673e9SRodney W. Grimes 
254dea673e9SRodney W. Grimes int
255dea673e9SRodney W. Grimes main(argc, argv)
256dea673e9SRodney W. Grimes 	int argc;
257dea673e9SRodney W. Grimes 	char *argv[];
258dea673e9SRodney W. Grimes {
259dea673e9SRodney W. Grimes 	int ch, i, quit, ret;
260eedc3436SMatthew Dillon 	int fileflag, ttyflag, vnodeflag;
26159392fe2SPoul-Henning Kamp 	char buf[_POSIX2_LINE_MAX],*opts;
262dea673e9SRodney W. Grimes 
263dea673e9SRodney W. Grimes 	fileflag = swapflag = ttyflag = vnodeflag = 0;
26459392fe2SPoul-Henning Kamp 
26559392fe2SPoul-Henning Kamp 	/* We will behave like good old swapinfo if thus invoked */
26659392fe2SPoul-Henning Kamp 	opts = strrchr(argv[0],'/');
26759392fe2SPoul-Henning Kamp 	if (opts)
26859392fe2SPoul-Henning Kamp 		opts++;
26959392fe2SPoul-Henning Kamp 	else
27059392fe2SPoul-Henning Kamp 		opts = argv[0];
27159392fe2SPoul-Henning Kamp 	if (!strcmp(opts,"swapinfo")) {
27259392fe2SPoul-Henning Kamp 		swapflag = 1;
2732d8e94a4SSujal Patel 		opts = "kM:N:";
274d9961cfdSPhilippe Charnier 		usagestr = "swapinfo [-k] [-M core] [-N system]";
27559392fe2SPoul-Henning Kamp 	} else {
27659392fe2SPoul-Henning Kamp 		opts = "TM:N:fiknstv";
277d9961cfdSPhilippe Charnier 		usagestr = "pstat [-Tfknstv] [-M core] [-N system]";
27859392fe2SPoul-Henning Kamp 	}
27959392fe2SPoul-Henning Kamp 
2806c3f552aSWarner Losh 	while ((ch = getopt(argc, argv, opts)) != -1)
281dea673e9SRodney W. Grimes 		switch (ch) {
282dea673e9SRodney W. Grimes 		case 'f':
283dea673e9SRodney W. Grimes 			fileflag = 1;
284dea673e9SRodney W. Grimes 			break;
28559392fe2SPoul-Henning Kamp 		case 'k':
28659392fe2SPoul-Henning Kamp 			putenv("BLOCKSIZE=1K");
28759392fe2SPoul-Henning Kamp 			break;
288dea673e9SRodney W. Grimes 		case 'M':
289dea673e9SRodney W. Grimes 			memf = optarg;
290dea673e9SRodney W. Grimes 			break;
291dea673e9SRodney W. Grimes 		case 'N':
292dea673e9SRodney W. Grimes 			nlistf = optarg;
293dea673e9SRodney W. Grimes 			break;
294dea673e9SRodney W. Grimes 		case 'n':
295dea673e9SRodney W. Grimes 			usenumflag = 1;
296dea673e9SRodney W. Grimes 			break;
297dea673e9SRodney W. Grimes 		case 's':
298eedc3436SMatthew Dillon 			++swapflag;
299dea673e9SRodney W. Grimes 			break;
300dea673e9SRodney W. Grimes 		case 'T':
301dea673e9SRodney W. Grimes 			totalflag = 1;
302dea673e9SRodney W. Grimes 			break;
303dea673e9SRodney W. Grimes 		case 't':
304dea673e9SRodney W. Grimes 			ttyflag = 1;
305dea673e9SRodney W. Grimes 			break;
306dea673e9SRodney W. Grimes 		case 'v':
307dea673e9SRodney W. Grimes 		case 'i':		/* Backward compatibility. */
308c4942498SDavid Greenman 			fprintf(stderr, "vnode mode not supported\n");
309c4942498SDavid Greenman 			exit(1);
310c4942498SDavid Greenman #if 0
311dea673e9SRodney W. Grimes 			vnodeflag = 1;
312dea673e9SRodney W. Grimes 			break;
313c4942498SDavid Greenman #endif
314dea673e9SRodney W. Grimes 		default:
315d9961cfdSPhilippe Charnier 			usage();
316dea673e9SRodney W. Grimes 		}
317dea673e9SRodney W. Grimes 	argc -= optind;
318dea673e9SRodney W. Grimes 	argv += optind;
319dea673e9SRodney W. Grimes 
320dea673e9SRodney W. Grimes 	/*
321dea673e9SRodney W. Grimes 	 * Discard setgid privileges if not the running kernel so that bad
322dea673e9SRodney W. Grimes 	 * guys can't print interesting stuff from kernel memory.
323dea673e9SRodney W. Grimes 	 */
324dea673e9SRodney W. Grimes 	if (nlistf != NULL || memf != NULL)
325dea673e9SRodney W. Grimes 		(void)setgid(getgid());
326dea673e9SRodney W. Grimes 
327dea673e9SRodney W. Grimes 	if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == 0)
328dea673e9SRodney W. Grimes 		errx(1, "kvm_openfiles: %s", buf);
329dea673e9SRodney W. Grimes 	if ((ret = kvm_nlist(kd, nl)) != 0) {
330dea673e9SRodney W. Grimes 		if (ret == -1)
331dea673e9SRodney W. Grimes 			errx(1, "kvm_nlist: %s", kvm_geterr(kd));
332eedc3436SMatthew Dillon 		for (i = NLMANDATORYBEG, quit = 0; i <= NLMANDATORYEND; i++)
333dea673e9SRodney W. Grimes 			if (!nl[i].n_value) {
334dea673e9SRodney W. Grimes 				quit = 1;
335d9961cfdSPhilippe Charnier 				warnx("undefined symbol: %s", nl[i].n_name);
336dea673e9SRodney W. Grimes 			}
337dea673e9SRodney W. Grimes 		if (quit)
338dea673e9SRodney W. Grimes 			exit(1);
339dea673e9SRodney W. Grimes 	}
340d9961cfdSPhilippe Charnier 	if (!(fileflag | vnodeflag | ttyflag | swapflag | totalflag))
341d9961cfdSPhilippe Charnier 		usage();
342dea673e9SRodney W. Grimes 	if (fileflag || totalflag)
343dea673e9SRodney W. Grimes 		filemode();
344c4942498SDavid Greenman 	if (vnodeflag)
345dea673e9SRodney W. Grimes 		vnodemode();
346dea673e9SRodney W. Grimes 	if (ttyflag)
347dea673e9SRodney W. Grimes 		ttymode();
348dea673e9SRodney W. Grimes 	if (swapflag || totalflag)
349dea673e9SRodney W. Grimes 		swapmode();
350dea673e9SRodney W. Grimes 	exit (0);
351dea673e9SRodney W. Grimes }
352dea673e9SRodney W. Grimes 
353d9961cfdSPhilippe Charnier static void
354d9961cfdSPhilippe Charnier usage()
355d9961cfdSPhilippe Charnier {
356d9961cfdSPhilippe Charnier 	fprintf(stderr, "usage: %s\n", usagestr);
357d9961cfdSPhilippe Charnier 	exit (1);
358d9961cfdSPhilippe Charnier }
359d9961cfdSPhilippe Charnier 
360dea673e9SRodney W. Grimes struct e_vnode {
361dea673e9SRodney W. Grimes 	struct vnode *avnode;
362dea673e9SRodney W. Grimes 	struct vnode vnode;
363dea673e9SRodney W. Grimes };
364dea673e9SRodney W. Grimes 
365dea673e9SRodney W. Grimes void
366dea673e9SRodney W. Grimes vnodemode()
367dea673e9SRodney W. Grimes {
3689c5cdfe0SPeter Wemm 	struct e_vnode *e_vnodebase, *endvnode, *evp;
3699c5cdfe0SPeter Wemm 	struct vnode *vp;
3709c5cdfe0SPeter Wemm 	struct mount *maddr, *mp;
371dea673e9SRodney W. Grimes 	int numvnodes;
372dea673e9SRodney W. Grimes 
373dea673e9SRodney W. Grimes 	e_vnodebase = loadvnodes(&numvnodes);
374dea673e9SRodney W. Grimes 	if (totalflag) {
375dea673e9SRodney W. Grimes 		(void)printf("%7d vnodes\n", numvnodes);
376dea673e9SRodney W. Grimes 		return;
377dea673e9SRodney W. Grimes 	}
378dea673e9SRodney W. Grimes 	endvnode = e_vnodebase + numvnodes;
379dea673e9SRodney W. Grimes 	(void)printf("%d active vnodes\n", numvnodes);
380dea673e9SRodney W. Grimes 
381dea673e9SRodney W. Grimes 
382dea673e9SRodney W. Grimes #define ST	mp->mnt_stat
383dea673e9SRodney W. Grimes 	maddr = NULL;
384dea673e9SRodney W. Grimes 	for (evp = e_vnodebase; evp < endvnode; evp++) {
385dea673e9SRodney W. Grimes 		vp = &evp->vnode;
386dea673e9SRodney W. Grimes 		if (vp->v_mount != maddr) {
387dea673e9SRodney W. Grimes 			/*
388dea673e9SRodney W. Grimes 			 * New filesystem
389dea673e9SRodney W. Grimes 			 */
390dea673e9SRodney W. Grimes 			if ((mp = getmnt(vp->v_mount)) == NULL)
391dea673e9SRodney W. Grimes 				continue;
392dea673e9SRodney W. Grimes 			maddr = vp->v_mount;
393dea673e9SRodney W. Grimes 			mount_print(mp);
394dea673e9SRodney W. Grimes 			vnode_header();
3959c5cdfe0SPeter Wemm 			if (!strcmp(ST.f_fstypename, "ufs") ||
3969c5cdfe0SPeter Wemm 			    !strcmp(ST.f_fstypename, "mfs"))
397dea673e9SRodney W. Grimes 				ufs_header();
3989c5cdfe0SPeter Wemm 			else if (!strcmp(ST.f_fstypename, "nfs"))
399dea673e9SRodney W. Grimes 				nfs_header();
4009c5cdfe0SPeter Wemm 			else if (!strcmp(ST.f_fstypename, "union"))
4019c5cdfe0SPeter Wemm 				union_header();
402dea673e9SRodney W. Grimes 			(void)printf("\n");
403dea673e9SRodney W. Grimes 		}
404dea673e9SRodney W. Grimes 		vnode_print(evp->avnode, vp);
4059c5cdfe0SPeter Wemm 		if (!strcmp(ST.f_fstypename, "ufs") ||
4069c5cdfe0SPeter Wemm 		    !strcmp(ST.f_fstypename, "mfs"))
407dea673e9SRodney W. Grimes 			ufs_print(vp);
4089c5cdfe0SPeter Wemm 		else if (!strcmp(ST.f_fstypename, "nfs"))
409dea673e9SRodney W. Grimes 			nfs_print(vp);
4109c5cdfe0SPeter Wemm 		else if (!strcmp(ST.f_fstypename, "union"))
4119c5cdfe0SPeter Wemm 			union_print(vp);
412dea673e9SRodney W. Grimes 		(void)printf("\n");
413dea673e9SRodney W. Grimes 	}
414dea673e9SRodney W. Grimes 	free(e_vnodebase);
415dea673e9SRodney W. Grimes }
416dea673e9SRodney W. Grimes 
417dea673e9SRodney W. Grimes void
418dea673e9SRodney W. Grimes vnode_header()
419dea673e9SRodney W. Grimes {
420dea673e9SRodney W. Grimes 	(void)printf("ADDR     TYP VFLAG  USE HOLD");
421dea673e9SRodney W. Grimes }
422dea673e9SRodney W. Grimes 
423dea673e9SRodney W. Grimes void
424dea673e9SRodney W. Grimes vnode_print(avnode, vp)
425dea673e9SRodney W. Grimes 	struct vnode *avnode;
426dea673e9SRodney W. Grimes 	struct vnode *vp;
427dea673e9SRodney W. Grimes {
428dea673e9SRodney W. Grimes 	char *type, flags[16];
429dea673e9SRodney W. Grimes 	char *fp = flags;
4309c5cdfe0SPeter Wemm 	int flag;
431dea673e9SRodney W. Grimes 
432dea673e9SRodney W. Grimes 	/*
433dea673e9SRodney W. Grimes 	 * set type
434dea673e9SRodney W. Grimes 	 */
435dea673e9SRodney W. Grimes 	switch (vp->v_type) {
436dea673e9SRodney W. Grimes 	case VNON:
437dea673e9SRodney W. Grimes 		type = "non"; break;
438dea673e9SRodney W. Grimes 	case VREG:
439dea673e9SRodney W. Grimes 		type = "reg"; break;
440dea673e9SRodney W. Grimes 	case VDIR:
441dea673e9SRodney W. Grimes 		type = "dir"; break;
442dea673e9SRodney W. Grimes 	case VBLK:
443dea673e9SRodney W. Grimes 		type = "blk"; break;
444dea673e9SRodney W. Grimes 	case VCHR:
445dea673e9SRodney W. Grimes 		type = "chr"; break;
446dea673e9SRodney W. Grimes 	case VLNK:
447dea673e9SRodney W. Grimes 		type = "lnk"; break;
448dea673e9SRodney W. Grimes 	case VSOCK:
449dea673e9SRodney W. Grimes 		type = "soc"; break;
450dea673e9SRodney W. Grimes 	case VFIFO:
451dea673e9SRodney W. Grimes 		type = "fif"; break;
452dea673e9SRodney W. Grimes 	case VBAD:
453dea673e9SRodney W. Grimes 		type = "bad"; break;
454dea673e9SRodney W. Grimes 	default:
455dea673e9SRodney W. Grimes 		type = "unk"; break;
456dea673e9SRodney W. Grimes 	}
457dea673e9SRodney W. Grimes 	/*
458dea673e9SRodney W. Grimes 	 * gather flags
459dea673e9SRodney W. Grimes 	 */
460dea673e9SRodney W. Grimes 	flag = vp->v_flag;
461dea673e9SRodney W. Grimes 	if (flag & VROOT)
462dea673e9SRodney W. Grimes 		*fp++ = 'R';
463dea673e9SRodney W. Grimes 	if (flag & VTEXT)
464dea673e9SRodney W. Grimes 		*fp++ = 'T';
465dea673e9SRodney W. Grimes 	if (flag & VSYSTEM)
466dea673e9SRodney W. Grimes 		*fp++ = 'S';
467fdaad796SPeter Wemm 	if (flag & VISTTY)
468fdaad796SPeter Wemm 		*fp++ = 't';
469dea673e9SRodney W. Grimes 	if (flag & VXLOCK)
470dea673e9SRodney W. Grimes 		*fp++ = 'L';
471dea673e9SRodney W. Grimes 	if (flag & VXWANT)
472dea673e9SRodney W. Grimes 		*fp++ = 'W';
473dea673e9SRodney W. Grimes 	if (flag & VBWAIT)
474dea673e9SRodney W. Grimes 		*fp++ = 'B';
475dea673e9SRodney W. Grimes 	if (flag & VALIASED)
476dea673e9SRodney W. Grimes 		*fp++ = 'A';
4775821aa7fSJohn Dyson 	if (flag & VOBJBUF)
478fdaad796SPeter Wemm 		*fp++ = 'V';
479fdaad796SPeter Wemm 	if (flag & VAGE)
480fdaad796SPeter Wemm 		*fp++ = 'a';
481fdaad796SPeter Wemm 	if (flag & VOLOCK)
482fdaad796SPeter Wemm 		*fp++ = 'l';
483fdaad796SPeter Wemm 	if (flag & VOWANT)
484fdaad796SPeter Wemm 		*fp++ = 'w';
485dea673e9SRodney W. Grimes 	if (flag == 0)
486dea673e9SRodney W. Grimes 		*fp++ = '-';
487dea673e9SRodney W. Grimes 	*fp = '\0';
488f6f60773SBruce Evans 	(void)printf("%8lx %s %5s %4d %4d",
489f6f60773SBruce Evans 	    (u_long)(void *)avnode, type, flags, vp->v_usecount, vp->v_holdcnt);
490dea673e9SRodney W. Grimes }
491dea673e9SRodney W. Grimes 
492dea673e9SRodney W. Grimes void
493dea673e9SRodney W. Grimes ufs_header()
494dea673e9SRodney W. Grimes {
495dea673e9SRodney W. Grimes 	(void)printf(" FILEID IFLAG RDEV|SZ");
496dea673e9SRodney W. Grimes }
497dea673e9SRodney W. Grimes 
498dea673e9SRodney W. Grimes int
499dea673e9SRodney W. Grimes ufs_print(vp)
500dea673e9SRodney W. Grimes 	struct vnode *vp;
501dea673e9SRodney W. Grimes {
5029c5cdfe0SPeter Wemm 	int flag;
503dea673e9SRodney W. Grimes 	struct inode inode, *ip = &inode;
504dea673e9SRodney W. Grimes 	char flagbuf[16], *flags = flagbuf;
505dea673e9SRodney W. Grimes 	char *name;
506dea673e9SRodney W. Grimes 	mode_t type;
507dea673e9SRodney W. Grimes 
508dea673e9SRodney W. Grimes 	KGETRET(VTOI(vp), &inode, sizeof(struct inode), "vnode's inode");
509dea673e9SRodney W. Grimes 	flag = ip->i_flag;
510dea673e9SRodney W. Grimes 	if (flag & IN_RENAME)
511dea673e9SRodney W. Grimes 		*flags++ = 'R';
512dea673e9SRodney W. Grimes 	if (flag & IN_UPDATE)
513dea673e9SRodney W. Grimes 		*flags++ = 'U';
514dea673e9SRodney W. Grimes 	if (flag & IN_ACCESS)
515dea673e9SRodney W. Grimes 		*flags++ = 'A';
516dea673e9SRodney W. Grimes 	if (flag & IN_CHANGE)
517dea673e9SRodney W. Grimes 		*flags++ = 'C';
518dea673e9SRodney W. Grimes 	if (flag & IN_MODIFIED)
519dea673e9SRodney W. Grimes 		*flags++ = 'M';
520dea673e9SRodney W. Grimes 	if (flag & IN_SHLOCK)
521dea673e9SRodney W. Grimes 		*flags++ = 'S';
522dea673e9SRodney W. Grimes 	if (flag & IN_EXLOCK)
523dea673e9SRodney W. Grimes 		*flags++ = 'E';
524dea673e9SRodney W. Grimes 	if (flag == 0)
525dea673e9SRodney W. Grimes 		*flags++ = '-';
526dea673e9SRodney W. Grimes 	*flags = '\0';
527dea673e9SRodney W. Grimes 
528dea673e9SRodney W. Grimes 	(void)printf(" %6d %5s", ip->i_number, flagbuf);
529dea673e9SRodney W. Grimes 	type = ip->i_mode & S_IFMT;
530dea673e9SRodney W. Grimes 	if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
531dea673e9SRodney W. Grimes 		if (usenumflag || ((name = devname(ip->i_rdev, type)) == NULL))
532dea673e9SRodney W. Grimes 			(void)printf("   %2d,%-2d",
533dea673e9SRodney W. Grimes 			    major(ip->i_rdev), minor(ip->i_rdev));
534dea673e9SRodney W. Grimes 		else
535dea673e9SRodney W. Grimes 			(void)printf(" %7s", name);
536dea673e9SRodney W. Grimes 	else
537dea673e9SRodney W. Grimes 		(void)printf(" %7qd", ip->i_size);
538dea673e9SRodney W. Grimes 	return (0);
539dea673e9SRodney W. Grimes }
540dea673e9SRodney W. Grimes 
541dea673e9SRodney W. Grimes void
542dea673e9SRodney W. Grimes nfs_header()
543dea673e9SRodney W. Grimes {
544dea673e9SRodney W. Grimes 	(void)printf(" FILEID NFLAG RDEV|SZ");
545dea673e9SRodney W. Grimes }
546dea673e9SRodney W. Grimes 
547dea673e9SRodney W. Grimes int
548dea673e9SRodney W. Grimes nfs_print(vp)
549dea673e9SRodney W. Grimes 	struct vnode *vp;
550dea673e9SRodney W. Grimes {
551dea673e9SRodney W. Grimes 	struct nfsnode nfsnode, *np = &nfsnode;
552dea673e9SRodney W. Grimes 	char flagbuf[16], *flags = flagbuf;
5539c5cdfe0SPeter Wemm 	int flag;
554dea673e9SRodney W. Grimes 	char *name;
555dea673e9SRodney W. Grimes 	mode_t type;
556dea673e9SRodney W. Grimes 
557dea673e9SRodney W. Grimes 	KGETRET(VTONFS(vp), &nfsnode, sizeof(nfsnode), "vnode's nfsnode");
558dea673e9SRodney W. Grimes 	flag = np->n_flag;
559dea673e9SRodney W. Grimes 	if (flag & NFLUSHWANT)
560dea673e9SRodney W. Grimes 		*flags++ = 'W';
561dea673e9SRodney W. Grimes 	if (flag & NFLUSHINPROG)
562dea673e9SRodney W. Grimes 		*flags++ = 'P';
563dea673e9SRodney W. Grimes 	if (flag & NMODIFIED)
564dea673e9SRodney W. Grimes 		*flags++ = 'M';
565dea673e9SRodney W. Grimes 	if (flag & NWRITEERR)
566dea673e9SRodney W. Grimes 		*flags++ = 'E';
567dea673e9SRodney W. Grimes 	if (flag & NQNFSNONCACHE)
568dea673e9SRodney W. Grimes 		*flags++ = 'X';
569dea673e9SRodney W. Grimes 	if (flag & NQNFSWRITE)
570dea673e9SRodney W. Grimes 		*flags++ = 'O';
571dea673e9SRodney W. Grimes 	if (flag & NQNFSEVICTED)
572dea673e9SRodney W. Grimes 		*flags++ = 'G';
573dea673e9SRodney W. Grimes 	if (flag == 0)
574dea673e9SRodney W. Grimes 		*flags++ = '-';
575dea673e9SRodney W. Grimes 	*flags = '\0';
576dea673e9SRodney W. Grimes 
577dea673e9SRodney W. Grimes #define VT	np->n_vattr
57878cda230SBruce Evans 	(void)printf(" %6ld %5s", VT.va_fileid, flagbuf);
579dea673e9SRodney W. Grimes 	type = VT.va_mode & S_IFMT;
580dea673e9SRodney W. Grimes 	if (S_ISCHR(VT.va_mode) || S_ISBLK(VT.va_mode))
581dea673e9SRodney W. Grimes 		if (usenumflag || ((name = devname(VT.va_rdev, type)) == NULL))
582dea673e9SRodney W. Grimes 			(void)printf("   %2d,%-2d",
583dea673e9SRodney W. Grimes 			    major(VT.va_rdev), minor(VT.va_rdev));
584dea673e9SRodney W. Grimes 		else
585dea673e9SRodney W. Grimes 			(void)printf(" %7s", name);
586dea673e9SRodney W. Grimes 	else
587dea673e9SRodney W. Grimes 		(void)printf(" %7qd", np->n_size);
588dea673e9SRodney W. Grimes 	return (0);
589dea673e9SRodney W. Grimes }
590dea673e9SRodney W. Grimes 
5919c5cdfe0SPeter Wemm void
5929c5cdfe0SPeter Wemm union_header()
5939c5cdfe0SPeter Wemm {
5949c5cdfe0SPeter Wemm 	(void)printf("    UPPER    LOWER");
5959c5cdfe0SPeter Wemm }
5969c5cdfe0SPeter Wemm 
5979c5cdfe0SPeter Wemm int
5989c5cdfe0SPeter Wemm union_print(vp)
5999c5cdfe0SPeter Wemm 	struct vnode *vp;
6009c5cdfe0SPeter Wemm {
6019c5cdfe0SPeter Wemm 	struct union_node unode, *up = &unode;
6029c5cdfe0SPeter Wemm 
6039c5cdfe0SPeter Wemm 	KGETRET(VTOUNION(vp), &unode, sizeof(unode), "vnode's unode");
6049c5cdfe0SPeter Wemm 
605f6f60773SBruce Evans 	(void)printf(" %8lx %8lx", (u_long)(void *)up->un_uppervp,
606f6f60773SBruce Evans 	    (u_long)(void *)up->un_lowervp);
6079c5cdfe0SPeter Wemm 	return (0);
6089c5cdfe0SPeter Wemm }
6099c5cdfe0SPeter Wemm 
610dea673e9SRodney W. Grimes /*
611dea673e9SRodney W. Grimes  * Given a pointer to a mount structure in kernel space,
612dea673e9SRodney W. Grimes  * read it in and return a usable pointer to it.
613dea673e9SRodney W. Grimes  */
614dea673e9SRodney W. Grimes struct mount *
615dea673e9SRodney W. Grimes getmnt(maddr)
616dea673e9SRodney W. Grimes 	struct mount *maddr;
617dea673e9SRodney W. Grimes {
618dea673e9SRodney W. Grimes 	static struct mtab {
619dea673e9SRodney W. Grimes 		struct mtab *next;
620dea673e9SRodney W. Grimes 		struct mount *maddr;
621dea673e9SRodney W. Grimes 		struct mount mount;
622dea673e9SRodney W. Grimes 	} *mhead = NULL;
6239c5cdfe0SPeter Wemm 	struct mtab *mt;
624dea673e9SRodney W. Grimes 
625dea673e9SRodney W. Grimes 	for (mt = mhead; mt != NULL; mt = mt->next)
626dea673e9SRodney W. Grimes 		if (maddr == mt->maddr)
627dea673e9SRodney W. Grimes 			return (&mt->mount);
628dea673e9SRodney W. Grimes 	if ((mt = malloc(sizeof(struct mtab))) == NULL)
629d9961cfdSPhilippe Charnier 		errx(1, "malloc");
630dea673e9SRodney W. Grimes 	KGETRET(maddr, &mt->mount, sizeof(struct mount), "mount table");
631dea673e9SRodney W. Grimes 	mt->maddr = maddr;
632dea673e9SRodney W. Grimes 	mt->next = mhead;
633dea673e9SRodney W. Grimes 	mhead = mt;
634dea673e9SRodney W. Grimes 	return (&mt->mount);
635dea673e9SRodney W. Grimes }
636dea673e9SRodney W. Grimes 
637dea673e9SRodney W. Grimes void
638dea673e9SRodney W. Grimes mount_print(mp)
639dea673e9SRodney W. Grimes 	struct mount *mp;
640dea673e9SRodney W. Grimes {
6419c5cdfe0SPeter Wemm 	int flags;
6429c5cdfe0SPeter Wemm 	const char *type;
643dea673e9SRodney W. Grimes 
644dea673e9SRodney W. Grimes #define ST	mp->mnt_stat
6459c5cdfe0SPeter Wemm 	(void)printf("*** MOUNT %s %s on %s", ST.f_fstypename,
6469c5cdfe0SPeter Wemm 	    ST.f_mntfromname, ST.f_mntonname);
647d9961cfdSPhilippe Charnier 	if ((flags = mp->mnt_flag)) {
6489c5cdfe0SPeter Wemm 		int i;
6499c5cdfe0SPeter Wemm 		const char *sep = " (";
650dea673e9SRodney W. Grimes 
6519c5cdfe0SPeter Wemm 		for (i = 0; mnt_flags[i].m_flag; i++) {
6529c5cdfe0SPeter Wemm 			if (flags & mnt_flags[i].m_flag) {
6539c5cdfe0SPeter Wemm 				(void)printf("%s%s", sep, mnt_flags[i].m_name);
6549c5cdfe0SPeter Wemm 				flags &= ~mnt_flags[i].m_flag;
6559c5cdfe0SPeter Wemm 				sep = ",";
656dea673e9SRodney W. Grimes 			}
657dea673e9SRodney W. Grimes 		}
658dea673e9SRodney W. Grimes 		if (flags)
6599c5cdfe0SPeter Wemm 			(void)printf("%sunknown_flags:%x", sep, flags);
660dea673e9SRodney W. Grimes 		(void)printf(")");
661dea673e9SRodney W. Grimes 	}
662dea673e9SRodney W. Grimes 	(void)printf("\n");
663dea673e9SRodney W. Grimes #undef ST
664dea673e9SRodney W. Grimes }
665dea673e9SRodney W. Grimes 
666dea673e9SRodney W. Grimes struct e_vnode *
667dea673e9SRodney W. Grimes loadvnodes(avnodes)
668dea673e9SRodney W. Grimes 	int *avnodes;
669dea673e9SRodney W. Grimes {
670dea673e9SRodney W. Grimes 	int mib[2];
671dea673e9SRodney W. Grimes 	size_t copysize;
672dea673e9SRodney W. Grimes 	struct e_vnode *vnodebase;
673dea673e9SRodney W. Grimes 
674dea673e9SRodney W. Grimes 	if (memf != NULL) {
675dea673e9SRodney W. Grimes 		/*
676dea673e9SRodney W. Grimes 		 * do it by hand
677dea673e9SRodney W. Grimes 		 */
678dea673e9SRodney W. Grimes 		return (kinfo_vnodes(avnodes));
679dea673e9SRodney W. Grimes 	}
680dea673e9SRodney W. Grimes 	mib[0] = CTL_KERN;
681dea673e9SRodney W. Grimes 	mib[1] = KERN_VNODE;
682dea673e9SRodney W. Grimes 	if (sysctl(mib, 2, NULL, &copysize, NULL, 0) == -1)
683dea673e9SRodney W. Grimes 		err(1, "sysctl: KERN_VNODE");
684dea673e9SRodney W. Grimes 	if ((vnodebase = malloc(copysize)) == NULL)
685d9961cfdSPhilippe Charnier 		errx(1, "malloc");
686dea673e9SRodney W. Grimes 	if (sysctl(mib, 2, vnodebase, &copysize, NULL, 0) == -1)
687dea673e9SRodney W. Grimes 		err(1, "sysctl: KERN_VNODE");
688dea673e9SRodney W. Grimes 	if (copysize % sizeof(struct e_vnode))
689dea673e9SRodney W. Grimes 		errx(1, "vnode size mismatch");
690dea673e9SRodney W. Grimes 	*avnodes = copysize / sizeof(struct e_vnode);
691dea673e9SRodney W. Grimes 
692dea673e9SRodney W. Grimes 	return (vnodebase);
693dea673e9SRodney W. Grimes }
694dea673e9SRodney W. Grimes 
695dea673e9SRodney W. Grimes /*
696dea673e9SRodney W. Grimes  * simulate what a running kernel does in in kinfo_vnode
697dea673e9SRodney W. Grimes  */
698dea673e9SRodney W. Grimes struct e_vnode *
699dea673e9SRodney W. Grimes kinfo_vnodes(avnodes)
700dea673e9SRodney W. Grimes 	int *avnodes;
701dea673e9SRodney W. Grimes {
702dea673e9SRodney W. Grimes 	struct mntlist mountlist;
70395cddebbSPeter Wemm 	struct mount *mp, mount, *mp_next;
70495cddebbSPeter Wemm 	struct vnode *vp, vnode, *vp_next;
705dea673e9SRodney W. Grimes 	char *vbuf, *evbuf, *bp;
706dea673e9SRodney W. Grimes 	int num, numvnodes;
707dea673e9SRodney W. Grimes 
708dea673e9SRodney W. Grimes #define VPTRSZ  sizeof(struct vnode *)
709dea673e9SRodney W. Grimes #define VNODESZ sizeof(struct vnode)
710dea673e9SRodney W. Grimes 
711dea673e9SRodney W. Grimes 	KGET(V_NUMV, numvnodes);
712dea673e9SRodney W. Grimes 	if ((vbuf = malloc((numvnodes + 20) * (VPTRSZ + VNODESZ))) == NULL)
713d9961cfdSPhilippe Charnier 		errx(1, "malloc");
714dea673e9SRodney W. Grimes 	bp = vbuf;
715dea673e9SRodney W. Grimes 	evbuf = vbuf + (numvnodes + 20) * (VPTRSZ + VNODESZ);
716dea673e9SRodney W. Grimes 	KGET(V_MOUNTLIST, mountlist);
71795cddebbSPeter Wemm 	for (num = 0, mp = mountlist.cqh_first; ; mp = mp_next) {
718dea673e9SRodney W. Grimes 		KGET2(mp, &mount, sizeof(mount), "mount entry");
71995cddebbSPeter Wemm 		mp_next = mount.mnt_list.cqe_next;
720dea673e9SRodney W. Grimes 		for (vp = mount.mnt_vnodelist.lh_first;
72195cddebbSPeter Wemm 		    vp != NULL; vp = vp_next) {
722dea673e9SRodney W. Grimes 			KGET2(vp, &vnode, sizeof(vnode), "vnode");
72395cddebbSPeter Wemm 			vp_next = vnode.v_mntvnodes.le_next;
724dea673e9SRodney W. Grimes 			if ((bp + VPTRSZ + VNODESZ) > evbuf)
725dea673e9SRodney W. Grimes 				/* XXX - should realloc */
726dea673e9SRodney W. Grimes 				errx(1, "no more room for vnodes");
727dea673e9SRodney W. Grimes 			memmove(bp, &vp, VPTRSZ);
728dea673e9SRodney W. Grimes 			bp += VPTRSZ;
729dea673e9SRodney W. Grimes 			memmove(bp, &vnode, VNODESZ);
730dea673e9SRodney W. Grimes 			bp += VNODESZ;
731dea673e9SRodney W. Grimes 			num++;
732dea673e9SRodney W. Grimes 		}
733d219a12eSDavid Greenman 		if (mp == mountlist.cqh_last)
734d219a12eSDavid Greenman 			break;
735dea673e9SRodney W. Grimes 	}
736dea673e9SRodney W. Grimes 	*avnodes = num;
737dea673e9SRodney W. Grimes 	return ((struct e_vnode *)vbuf);
738dea673e9SRodney W. Grimes }
739dea673e9SRodney W. Grimes 
7400b8a3ff7SBruce Evans char hdr[] =
741f6f60773SBruce Evans "  LINE RAW CAN OUT IHIWT ILOWT OHWT LWT     COL STATE  SESS      PGID DISC\n";
742dea673e9SRodney W. Grimes int ttyspace = 128;
743dea673e9SRodney W. Grimes 
744dea673e9SRodney W. Grimes void
745dea673e9SRodney W. Grimes ttymode()
746dea673e9SRodney W. Grimes {
747dea673e9SRodney W. Grimes 	struct tty *tty;
748dea673e9SRodney W. Grimes 
749dea673e9SRodney W. Grimes 	if ((tty = malloc(ttyspace * sizeof(*tty))) == NULL)
750d9961cfdSPhilippe Charnier 		errx(1, "malloc");
7519c5cdfe0SPeter Wemm #if !defined(hp300) && !defined(mips)
7525a3391bfSAndrey A. Chernov 	if (nl[SCONS].n_type != 0) {
753dea673e9SRodney W. Grimes 		(void)printf("1 console\n");
754dea673e9SRodney W. Grimes 		KGET(SCONS, *tty);
755dea673e9SRodney W. Grimes 		(void)printf(hdr);
756dea673e9SRodney W. Grimes 		ttyprt(&tty[0], 0);
7575a3391bfSAndrey A. Chernov 	}
758dea673e9SRodney W. Grimes #endif
759dea673e9SRodney W. Grimes #ifdef vax
760dea673e9SRodney W. Grimes 	if (nl[SNQD].n_type != 0)
761dea673e9SRodney W. Grimes 		qdss();
762dea673e9SRodney W. Grimes 	if (nl[SNDZ].n_type != 0)
763a9aa8c37SPeter Wemm 		ttytype(tty, "dz", SDZ, SNDZ, 0);
764dea673e9SRodney W. Grimes 	if (nl[SNDH].n_type != 0)
765a9aa8c37SPeter Wemm 		ttytype(tty, "dh", SDH, SNDH, 0);
766dea673e9SRodney W. Grimes 	if (nl[SNDMF].n_type != 0)
767a9aa8c37SPeter Wemm 		ttytype(tty, "dmf", SDMF, SNDMF, 0);
768dea673e9SRodney W. Grimes 	if (nl[SNDHU].n_type != 0)
769a9aa8c37SPeter Wemm 		ttytype(tty, "dhu", SDHU, SNDHU, 0);
770dea673e9SRodney W. Grimes 	if (nl[SNDMZ].n_type != 0)
771a9aa8c37SPeter Wemm 		ttytype(tty, "dmz", SDMZ, SNDMZ, 0);
772dea673e9SRodney W. Grimes #endif
773dea673e9SRodney W. Grimes #ifdef tahoe
774dea673e9SRodney W. Grimes 	if (nl[SNVX].n_type != 0)
775a9aa8c37SPeter Wemm 		ttytype(tty, "vx", SVX, SNVX, 0);
776dea673e9SRodney W. Grimes 	if (nl[SNMP].n_type != 0)
777a9aa8c37SPeter Wemm 		ttytype(tty, "mp", SMP, SNMP, 0);
778dea673e9SRodney W. Grimes #endif
779dea673e9SRodney W. Grimes #ifdef hp300
780dea673e9SRodney W. Grimes 	if (nl[SNITE].n_type != 0)
781a9aa8c37SPeter Wemm 		ttytype(tty, "ite", SITE, SNITE, 0);
782dea673e9SRodney W. Grimes 	if (nl[SNDCA].n_type != 0)
783a9aa8c37SPeter Wemm 		ttytype(tty, "dca", SDCA, SNDCA, 0);
784dea673e9SRodney W. Grimes 	if (nl[SNDCM].n_type != 0)
785a9aa8c37SPeter Wemm 		ttytype(tty, "dcm", SDCM, SNDCM, 0);
786dea673e9SRodney W. Grimes 	if (nl[SNDCL].n_type != 0)
787a9aa8c37SPeter Wemm 		ttytype(tty, "dcl", SDCL, SNDCL, 0);
788dea673e9SRodney W. Grimes #endif
789dea673e9SRodney W. Grimes #ifdef mips
790dea673e9SRodney W. Grimes 	if (nl[SNDC].n_type != 0)
791a9aa8c37SPeter Wemm 		ttytype(tty, "dc", SDC, SNDC, 0);
792dea673e9SRodney W. Grimes #endif
7935a3391bfSAndrey A. Chernov #ifdef __FreeBSD__
794de4c8be3SSøren Schmidt 	if (nl[NSCCONS].n_type != 0)
795a9aa8c37SPeter Wemm 		ttytype(tty, "vty", SCCONS, NSCCONS, 0);
79690300419SAndrey A. Chernov 	if (nl[NSIO].n_type != 0)
797a9aa8c37SPeter Wemm 		ttytype(tty, "sio", SIO, NSIO, 0);
79890300419SAndrey A. Chernov 	if (nl[NRC].n_type != 0)
799a9aa8c37SPeter Wemm 		ttytype(tty, "rc", RC, NRC, 0);
80024f769b0SBruce Evans 	if (nl[NCY].n_type != 0)
801a9aa8c37SPeter Wemm 		ttytype(tty, "cy", CY, NCY, 0);
802a9aa8c37SPeter Wemm 	if (nl[NSI].n_type != 0)
803a9aa8c37SPeter Wemm 		ttytype(tty, "si", SI, NSI, 1);
8045a3391bfSAndrey A. Chernov #endif
805dea673e9SRodney W. Grimes 	if (nl[SNPTY].n_type != 0)
806a9aa8c37SPeter Wemm 		ttytype(tty, "pty", SPTY, SNPTY, 0);
807dea673e9SRodney W. Grimes }
808dea673e9SRodney W. Grimes 
809dea673e9SRodney W. Grimes void
810a9aa8c37SPeter Wemm ttytype(tty, name, type, number, indir)
8119c5cdfe0SPeter Wemm 	struct tty *tty;
812dea673e9SRodney W. Grimes 	char *name;
813a9aa8c37SPeter Wemm 	int type, number, indir;
814dea673e9SRodney W. Grimes {
8159c5cdfe0SPeter Wemm 	struct tty *tp;
816dea673e9SRodney W. Grimes 	int ntty;
817a9aa8c37SPeter Wemm 	struct tty **ttyaddr;
818dea673e9SRodney W. Grimes 
819dea673e9SRodney W. Grimes 	if (tty == NULL)
820dea673e9SRodney W. Grimes 		return;
821dea673e9SRodney W. Grimes 	KGET(number, ntty);
822dea673e9SRodney W. Grimes 	(void)printf("%d %s %s\n", ntty, name, (ntty == 1) ? "line" : "lines");
823dea673e9SRodney W. Grimes 	if (ntty > ttyspace) {
824dea673e9SRodney W. Grimes 		ttyspace = ntty;
825dea673e9SRodney W. Grimes 		if ((tty = realloc(tty, ttyspace * sizeof(*tty))) == 0)
826d9961cfdSPhilippe Charnier 			errx(1, "realloc");
827dea673e9SRodney W. Grimes 	}
828a9aa8c37SPeter Wemm 	if (indir) {
829a9aa8c37SPeter Wemm 		KGET(type, ttyaddr);
830a9aa8c37SPeter Wemm 		KGET2(ttyaddr, tty, ntty * sizeof(struct tty), "tty structs");
831a9aa8c37SPeter Wemm 	} else {
832dea673e9SRodney W. Grimes 		KGET1(type, tty, ntty * sizeof(struct tty), "tty structs");
833a9aa8c37SPeter Wemm 	}
834dea673e9SRodney W. Grimes 	(void)printf(hdr);
835dea673e9SRodney W. Grimes 	for (tp = tty; tp < &tty[ntty]; tp++)
836dea673e9SRodney W. Grimes 		ttyprt(tp, tp - tty);
837dea673e9SRodney W. Grimes }
838dea673e9SRodney W. Grimes 
839dea673e9SRodney W. Grimes struct {
840dea673e9SRodney W. Grimes 	int flag;
841dea673e9SRodney W. Grimes 	char val;
842dea673e9SRodney W. Grimes } ttystates[] = {
84324f769b0SBruce Evans #ifdef TS_WOPEN
844dea673e9SRodney W. Grimes 	{ TS_WOPEN,	'W'},
84524f769b0SBruce Evans #endif
846dea673e9SRodney W. Grimes 	{ TS_ISOPEN,	'O'},
847dea673e9SRodney W. Grimes 	{ TS_CARR_ON,	'C'},
84824f769b0SBruce Evans #ifdef TS_CONNECTED
84924f769b0SBruce Evans 	{ TS_CONNECTED,	'c'},
85024f769b0SBruce Evans #endif
851dea673e9SRodney W. Grimes 	{ TS_TIMEOUT,	'T'},
852dea673e9SRodney W. Grimes 	{ TS_FLUSH,	'F'},
853dea673e9SRodney W. Grimes 	{ TS_BUSY,	'B'},
85424f769b0SBruce Evans #ifdef TS_ASLEEP
855dea673e9SRodney W. Grimes 	{ TS_ASLEEP,	'A'},
85624f769b0SBruce Evans #endif
85724f769b0SBruce Evans #ifdef TS_SO_OLOWAT
85824f769b0SBruce Evans 	{ TS_SO_OLOWAT,	'A'},
85924f769b0SBruce Evans #endif
86024f769b0SBruce Evans #ifdef TS_SO_OCOMPLETE
86124f769b0SBruce Evans 	{ TS_SO_OCOMPLETE, 'a'},
86224f769b0SBruce Evans #endif
863dea673e9SRodney W. Grimes 	{ TS_XCLUDE,	'X'},
864dea673e9SRodney W. Grimes 	{ TS_TTSTOP,	'S'},
86524f769b0SBruce Evans #ifdef TS_CAR_OFLOW
86624f769b0SBruce Evans 	{ TS_CAR_OFLOW,	'm'},
86724f769b0SBruce Evans #endif
86824f769b0SBruce Evans #ifdef TS_CTS_OFLOW
86924f769b0SBruce Evans 	{ TS_CTS_OFLOW,	'o'},
87024f769b0SBruce Evans #endif
87124f769b0SBruce Evans #ifdef TS_DSR_OFLOW
87224f769b0SBruce Evans 	{ TS_DSR_OFLOW,	'd'},
87324f769b0SBruce Evans #endif
874dea673e9SRodney W. Grimes 	{ TS_TBLOCK,	'K'},
875dea673e9SRodney W. Grimes 	{ TS_ASYNC,	'Y'},
876dea673e9SRodney W. Grimes 	{ TS_BKSL,	'D'},
877dea673e9SRodney W. Grimes 	{ TS_ERASE,	'E'},
878dea673e9SRodney W. Grimes 	{ TS_LNCH,	'L'},
879dea673e9SRodney W. Grimes 	{ TS_TYPEN,	'P'},
880dea673e9SRodney W. Grimes 	{ TS_CNTTB,	'N'},
88124f769b0SBruce Evans #ifdef TS_CAN_BYPASS_L_RINT
882020531ceSAndrey A. Chernov 	{ TS_CAN_BYPASS_L_RINT, 'l'},
883020531ceSAndrey A. Chernov #endif
88424f769b0SBruce Evans #ifdef TS_SNOOP
88524f769b0SBruce Evans 	{ TS_SNOOP,     's'},
88624f769b0SBruce Evans #endif
88724f769b0SBruce Evans #ifdef TS_ZOMBIE
88824f769b0SBruce Evans 	{ TS_ZOMBIE,	'Z'},
88924f769b0SBruce Evans #endif
890dea673e9SRodney W. Grimes 	{ 0,	       '\0'},
891dea673e9SRodney W. Grimes };
892dea673e9SRodney W. Grimes 
893dea673e9SRodney W. Grimes void
894dea673e9SRodney W. Grimes ttyprt(tp, line)
8959c5cdfe0SPeter Wemm 	struct tty *tp;
896dea673e9SRodney W. Grimes 	int line;
897dea673e9SRodney W. Grimes {
8989c5cdfe0SPeter Wemm 	int i, j;
899dea673e9SRodney W. Grimes 	pid_t pgid;
900dea673e9SRodney W. Grimes 	char *name, state[20];
901dea673e9SRodney W. Grimes 
902dea673e9SRodney W. Grimes 	if (usenumflag || tp->t_dev == 0 ||
903dea673e9SRodney W. Grimes 	   (name = devname(tp->t_dev, S_IFCHR)) == NULL)
904dea673e9SRodney W. Grimes 		(void)printf("%7d ", line);
905dea673e9SRodney W. Grimes 	else
906dea673e9SRodney W. Grimes 		(void)printf("%7s ", name);
907dea673e9SRodney W. Grimes 	(void)printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc);
908f6f60773SBruce Evans 	(void)printf("%3d %5d %5d %4d %3d %7d ", tp->t_outq.c_cc,
9090b8a3ff7SBruce Evans 		tp->t_ihiwat, tp->t_ilowat, tp->t_ohiwat, tp->t_olowat,
9100b8a3ff7SBruce Evans 		tp->t_column);
911dea673e9SRodney W. Grimes 	for (i = j = 0; ttystates[i].flag; i++)
912dea673e9SRodney W. Grimes 		if (tp->t_state&ttystates[i].flag)
913dea673e9SRodney W. Grimes 			state[j++] = ttystates[i].val;
914dea673e9SRodney W. Grimes 	if (j == 0)
915dea673e9SRodney W. Grimes 		state[j++] = '-';
916dea673e9SRodney W. Grimes 	state[j] = '\0';
917f6f60773SBruce Evans 	(void)printf("%-6s %8lx", state, (u_long)(void *)tp->t_session);
918dea673e9SRodney W. Grimes 	pgid = 0;
919dea673e9SRodney W. Grimes 	if (tp->t_pgrp != NULL)
920dea673e9SRodney W. Grimes 		KGET2(&tp->t_pgrp->pg_id, &pgid, sizeof(pid_t), "pgid");
921dea673e9SRodney W. Grimes 	(void)printf("%6d ", pgid);
922dea673e9SRodney W. Grimes 	switch (tp->t_line) {
923dea673e9SRodney W. Grimes 	case TTYDISC:
924dea673e9SRodney W. Grimes 		(void)printf("term\n");
925dea673e9SRodney W. Grimes 		break;
92690300419SAndrey A. Chernov 	case NTTYDISC:
92790300419SAndrey A. Chernov 		(void)printf("ntty\n");
92890300419SAndrey A. Chernov 		break;
929dea673e9SRodney W. Grimes 	case TABLDISC:
930dea673e9SRodney W. Grimes 		(void)printf("tab\n");
931dea673e9SRodney W. Grimes 		break;
932dea673e9SRodney W. Grimes 	case SLIPDISC:
933dea673e9SRodney W. Grimes 		(void)printf("slip\n");
934dea673e9SRodney W. Grimes 		break;
93590300419SAndrey A. Chernov 	case PPPDISC:
93690300419SAndrey A. Chernov 		(void)printf("ppp\n");
93790300419SAndrey A. Chernov 		break;
938dea673e9SRodney W. Grimes 	default:
939dea673e9SRodney W. Grimes 		(void)printf("%d\n", tp->t_line);
940dea673e9SRodney W. Grimes 		break;
941dea673e9SRodney W. Grimes 	}
942dea673e9SRodney W. Grimes }
943dea673e9SRodney W. Grimes 
944dea673e9SRodney W. Grimes void
945dea673e9SRodney W. Grimes filemode()
946dea673e9SRodney W. Grimes {
9479c5cdfe0SPeter Wemm 	struct file *fp;
948dea673e9SRodney W. Grimes 	struct file *addr;
949dea673e9SRodney W. Grimes 	char *buf, flagbuf[16], *fbp;
950dea673e9SRodney W. Grimes 	int len, maxfile, nfile;
951dea673e9SRodney W. Grimes 	static char *dtypes[] = { "???", "inode", "socket" };
952dea673e9SRodney W. Grimes 
953dea673e9SRodney W. Grimes 	KGET(FNL_MAXFILE, maxfile);
954dea673e9SRodney W. Grimes 	if (totalflag) {
955dea673e9SRodney W. Grimes 		KGET(FNL_NFILE, nfile);
956dea673e9SRodney W. Grimes 		(void)printf("%3d/%3d files\n", nfile, maxfile);
957dea673e9SRodney W. Grimes 		return;
958dea673e9SRodney W. Grimes 	}
959dea673e9SRodney W. Grimes 	if (getfiles(&buf, &len) == -1)
960dea673e9SRodney W. Grimes 		return;
961dea673e9SRodney W. Grimes 	/*
962dea673e9SRodney W. Grimes 	 * Getfiles returns in malloc'd memory a pointer to the first file
963dea673e9SRodney W. Grimes 	 * structure, and then an array of file structs (whose addresses are
964dea673e9SRodney W. Grimes 	 * derivable from the previous entry).
965dea673e9SRodney W. Grimes 	 */
96698d69008SJeffrey Hsu 	addr = ((struct filelist *)buf)->lh_first;
96798d69008SJeffrey Hsu 	fp = (struct file *)(buf + sizeof(struct filelist));
96898d69008SJeffrey Hsu 	nfile = (len - sizeof(struct filelist)) / sizeof(struct file);
969dea673e9SRodney W. Grimes 
970dea673e9SRodney W. Grimes 	(void)printf("%d/%d open files\n", nfile, maxfile);
971dea673e9SRodney W. Grimes 	(void)printf("   LOC   TYPE    FLG     CNT  MSG    DATA    OFFSET\n");
97298d69008SJeffrey Hsu 	for (; (char *)fp < buf + len; addr = fp->f_list.le_next, fp++) {
973dea673e9SRodney W. Grimes 		if ((unsigned)fp->f_type > DTYPE_SOCKET)
974dea673e9SRodney W. Grimes 			continue;
975f6f60773SBruce Evans 		(void)printf("%8lx ", (u_long)(void *)addr);
976dea673e9SRodney W. Grimes 		(void)printf("%-8.8s", dtypes[fp->f_type]);
977dea673e9SRodney W. Grimes 		fbp = flagbuf;
978dea673e9SRodney W. Grimes 		if (fp->f_flag & FREAD)
979dea673e9SRodney W. Grimes 			*fbp++ = 'R';
980dea673e9SRodney W. Grimes 		if (fp->f_flag & FWRITE)
981dea673e9SRodney W. Grimes 			*fbp++ = 'W';
982dea673e9SRodney W. Grimes 		if (fp->f_flag & FAPPEND)
983dea673e9SRodney W. Grimes 			*fbp++ = 'A';
984dea673e9SRodney W. Grimes #ifdef FSHLOCK	/* currently gone */
985dea673e9SRodney W. Grimes 		if (fp->f_flag & FSHLOCK)
986dea673e9SRodney W. Grimes 			*fbp++ = 'S';
987dea673e9SRodney W. Grimes 		if (fp->f_flag & FEXLOCK)
988dea673e9SRodney W. Grimes 			*fbp++ = 'X';
989dea673e9SRodney W. Grimes #endif
990dea673e9SRodney W. Grimes 		if (fp->f_flag & FASYNC)
991dea673e9SRodney W. Grimes 			*fbp++ = 'I';
992dea673e9SRodney W. Grimes 		*fbp = '\0';
993dea673e9SRodney W. Grimes 		(void)printf("%6s  %3d", flagbuf, fp->f_count);
994dea673e9SRodney W. Grimes 		(void)printf("  %3d", fp->f_msgcount);
995f6f60773SBruce Evans 		(void)printf("  %8lx", (u_long)(void *)fp->f_data);
996dea673e9SRodney W. Grimes 		if (fp->f_offset < 0)
997dea673e9SRodney W. Grimes 			(void)printf("  %qx\n", fp->f_offset);
998dea673e9SRodney W. Grimes 		else
999dea673e9SRodney W. Grimes 			(void)printf("  %qd\n", fp->f_offset);
1000dea673e9SRodney W. Grimes 	}
1001dea673e9SRodney W. Grimes 	free(buf);
1002dea673e9SRodney W. Grimes }
1003dea673e9SRodney W. Grimes 
1004dea673e9SRodney W. Grimes int
1005dea673e9SRodney W. Grimes getfiles(abuf, alen)
1006dea673e9SRodney W. Grimes 	char **abuf;
1007dea673e9SRodney W. Grimes 	int *alen;
1008dea673e9SRodney W. Grimes {
1009dea673e9SRodney W. Grimes 	size_t len;
1010dea673e9SRodney W. Grimes 	int mib[2];
1011dea673e9SRodney W. Grimes 	char *buf;
1012dea673e9SRodney W. Grimes 
1013dea673e9SRodney W. Grimes 	/*
1014dea673e9SRodney W. Grimes 	 * XXX
1015dea673e9SRodney W. Grimes 	 * Add emulation of KINFO_FILE here.
1016dea673e9SRodney W. Grimes 	 */
1017dea673e9SRodney W. Grimes 	if (memf != NULL)
1018d9961cfdSPhilippe Charnier 		errx(1, "files on dead kernel, not implemented");
1019dea673e9SRodney W. Grimes 
1020dea673e9SRodney W. Grimes 	mib[0] = CTL_KERN;
1021dea673e9SRodney W. Grimes 	mib[1] = KERN_FILE;
1022dea673e9SRodney W. Grimes 	if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1) {
1023dea673e9SRodney W. Grimes 		warn("sysctl: KERN_FILE");
1024dea673e9SRodney W. Grimes 		return (-1);
1025dea673e9SRodney W. Grimes 	}
1026dea673e9SRodney W. Grimes 	if ((buf = malloc(len)) == NULL)
1027d9961cfdSPhilippe Charnier 		errx(1, "malloc");
1028dea673e9SRodney W. Grimes 	if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) {
1029dea673e9SRodney W. Grimes 		warn("sysctl: KERN_FILE");
1030dea673e9SRodney W. Grimes 		return (-1);
1031dea673e9SRodney W. Grimes 	}
1032dea673e9SRodney W. Grimes 	*abuf = buf;
1033dea673e9SRodney W. Grimes 	*alen = len;
1034dea673e9SRodney W. Grimes 	return (0);
1035dea673e9SRodney W. Grimes }
1036dea673e9SRodney W. Grimes 
1037dea673e9SRodney W. Grimes /*
1038eedc3436SMatthew Dillon  * scanradix() - used by swapmode() to scan the swap device's new style
1039eedc3436SMatthew Dillon  * 		 radix tree
1040eedc3436SMatthew Dillon  */
1041eedc3436SMatthew Dillon 
1042eedc3436SMatthew Dillon #define TABME	tab, tab, ""
1043eedc3436SMatthew Dillon 
1044eedc3436SMatthew Dillon int
1045eedc3436SMatthew Dillon scanradix(
1046eedc3436SMatthew Dillon 	blmeta_t *scan,
1047eedc3436SMatthew Dillon 	daddr_t blk,
1048eedc3436SMatthew Dillon 	daddr_t radix,
1049eedc3436SMatthew Dillon 	daddr_t skip,
1050eedc3436SMatthew Dillon 	daddr_t count,
1051eedc3436SMatthew Dillon 	int dmmax,
1052eedc3436SMatthew Dillon 	int nswdev,
1053eedc3436SMatthew Dillon 	long *perdev,
1054eedc3436SMatthew Dillon 	int tab
1055eedc3436SMatthew Dillon ) {
1056eedc3436SMatthew Dillon 	blmeta_t meta;
1057eedc3436SMatthew Dillon 
1058eedc3436SMatthew Dillon 	KGET2(scan, &meta, sizeof(meta), "blmeta_t");
1059eedc3436SMatthew Dillon 
1060eedc3436SMatthew Dillon 	/*
1061eedc3436SMatthew Dillon 	 * Terminator
1062eedc3436SMatthew Dillon 	 */
1063eedc3436SMatthew Dillon 	if (meta.bm_bighint == (daddr_t)-1) {
1064eedc3436SMatthew Dillon 		if (swapflag > 1) {
1065eedc3436SMatthew Dillon 			printf("%*.*s(0x%06x,%d) Terminator\n",
1066eedc3436SMatthew Dillon 			    TABME,
1067eedc3436SMatthew Dillon 			    blk,
1068eedc3436SMatthew Dillon 			    radix
1069eedc3436SMatthew Dillon 			);
1070eedc3436SMatthew Dillon 		}
1071eedc3436SMatthew Dillon 		return(-1);
1072eedc3436SMatthew Dillon 	}
1073eedc3436SMatthew Dillon 
1074eedc3436SMatthew Dillon 	if (radix == BLIST_BMAP_RADIX) {
1075eedc3436SMatthew Dillon 		/*
1076eedc3436SMatthew Dillon 		 * Leaf bitmap
1077eedc3436SMatthew Dillon 		 */
1078eedc3436SMatthew Dillon 		int i;
1079eedc3436SMatthew Dillon 
1080eedc3436SMatthew Dillon 		if (swapflag > 1) {
1081eedc3436SMatthew Dillon 			printf("%*.*s(0x%06x,%d) Bitmap %08x big=%d\n",
1082eedc3436SMatthew Dillon 			    TABME,
1083eedc3436SMatthew Dillon 			    blk,
1084eedc3436SMatthew Dillon 			    radix,
1085eedc3436SMatthew Dillon 			    (int)meta.u.bmu_bitmap,
1086eedc3436SMatthew Dillon 			    meta.bm_bighint
1087eedc3436SMatthew Dillon 			);
1088eedc3436SMatthew Dillon 		}
1089eedc3436SMatthew Dillon 
1090eedc3436SMatthew Dillon 		/*
1091eedc3436SMatthew Dillon 		 * If not all allocated, count.
1092eedc3436SMatthew Dillon 		 */
1093eedc3436SMatthew Dillon 		if (meta.u.bmu_bitmap != 0) {
1094eedc3436SMatthew Dillon 			for (i = 0; i < BLIST_BMAP_RADIX && i < count; ++i) {
1095eedc3436SMatthew Dillon 				/*
1096eedc3436SMatthew Dillon 				 * A 0 bit means allocated
1097eedc3436SMatthew Dillon 				 */
1098eedc3436SMatthew Dillon 				if ((meta.u.bmu_bitmap & (1 << i))) {
1099eedc3436SMatthew Dillon 					int t = 0;
1100eedc3436SMatthew Dillon 
1101eedc3436SMatthew Dillon 					if (nswdev)
1102eedc3436SMatthew Dillon 						t = (blk + i) / dmmax % nswdev;
1103eedc3436SMatthew Dillon 					++perdev[t];
1104eedc3436SMatthew Dillon 				}
1105eedc3436SMatthew Dillon 			}
1106eedc3436SMatthew Dillon 		}
1107eedc3436SMatthew Dillon 	} else if (meta.u.bmu_avail == radix) {
1108eedc3436SMatthew Dillon 		/*
1109eedc3436SMatthew Dillon 		 * Meta node if all free
1110eedc3436SMatthew Dillon 		 */
1111eedc3436SMatthew Dillon 		if (swapflag > 1) {
1112eedc3436SMatthew Dillon 			printf("%*.*s(0x%06x,%d) Submap ALL-FREE {\n",
1113eedc3436SMatthew Dillon 			    TABME,
1114eedc3436SMatthew Dillon 			    blk,
1115eedc3436SMatthew Dillon 			    radix,
1116eedc3436SMatthew Dillon 			    (int)meta.u.bmu_avail,
1117eedc3436SMatthew Dillon 			    meta.bm_bighint
1118eedc3436SMatthew Dillon 			);
1119eedc3436SMatthew Dillon 		}
1120eedc3436SMatthew Dillon 		/*
1121eedc3436SMatthew Dillon 		 * Note: both dmmax and radix are powers of 2.  However, dmmax
1122eedc3436SMatthew Dillon 		 * may be larger then radix so use a smaller increment if
1123eedc3436SMatthew Dillon 		 * necessary.
1124eedc3436SMatthew Dillon 		 */
1125eedc3436SMatthew Dillon 		{
1126eedc3436SMatthew Dillon 			int t;
1127eedc3436SMatthew Dillon 			int tinc = dmmax;
1128eedc3436SMatthew Dillon 
1129eedc3436SMatthew Dillon 			while (tinc > radix)
1130eedc3436SMatthew Dillon 				tinc >>= 1;
1131eedc3436SMatthew Dillon 
1132eedc3436SMatthew Dillon 			for (t = blk; t < blk + radix; t += tinc) {
1133eedc3436SMatthew Dillon 				if (nswdev)
1134eedc3436SMatthew Dillon 					perdev[0] += tinc;
1135eedc3436SMatthew Dillon 				else
1136eedc3436SMatthew Dillon 					perdev[t / dmmax % nswdev] += tinc;
1137eedc3436SMatthew Dillon 			}
1138eedc3436SMatthew Dillon 		}
1139eedc3436SMatthew Dillon 	} else if (meta.u.bmu_avail == 0) {
1140eedc3436SMatthew Dillon 		/*
1141eedc3436SMatthew Dillon 		 * Meta node if all used
1142eedc3436SMatthew Dillon 		 */
1143eedc3436SMatthew Dillon 		if (swapflag > 1) {
1144eedc3436SMatthew Dillon 			printf("%*.*s(0x%06x,%d) Submap ALL-ALLOCATED\n",
1145eedc3436SMatthew Dillon 			    TABME,
1146eedc3436SMatthew Dillon 			    blk,
1147eedc3436SMatthew Dillon 			    radix,
1148eedc3436SMatthew Dillon 			    (int)meta.u.bmu_avail,
1149eedc3436SMatthew Dillon 			    meta.bm_bighint
1150eedc3436SMatthew Dillon 			);
1151eedc3436SMatthew Dillon 		}
1152eedc3436SMatthew Dillon 	} else {
1153eedc3436SMatthew Dillon 		/*
1154eedc3436SMatthew Dillon 		 * Meta node if not all free
1155eedc3436SMatthew Dillon 		 */
1156eedc3436SMatthew Dillon 		int i;
1157eedc3436SMatthew Dillon 		int next_skip;
1158eedc3436SMatthew Dillon 
1159eedc3436SMatthew Dillon 		radix >>= BLIST_META_RADIX_SHIFT;
1160eedc3436SMatthew Dillon 		next_skip = skip >> BLIST_META_RADIX_SHIFT;
1161eedc3436SMatthew Dillon 
1162eedc3436SMatthew Dillon 		if (swapflag > 1) {
1163eedc3436SMatthew Dillon 			printf("%*.*s(0x%06x,%d) Submap avail=%d big=%d {\n",
1164eedc3436SMatthew Dillon 			    TABME,
1165eedc3436SMatthew Dillon 			    blk,
1166eedc3436SMatthew Dillon 			    radix,
1167eedc3436SMatthew Dillon 			    (int)meta.u.bmu_avail,
1168eedc3436SMatthew Dillon 			    meta.bm_bighint
1169eedc3436SMatthew Dillon 			);
1170eedc3436SMatthew Dillon 		}
1171eedc3436SMatthew Dillon 
1172eedc3436SMatthew Dillon 		for (i = 1; i <= skip; i += next_skip) {
1173eedc3436SMatthew Dillon 			int r;
1174eedc3436SMatthew Dillon 			daddr_t vcount = (count > radix) ? radix : count;
1175eedc3436SMatthew Dillon 
1176eedc3436SMatthew Dillon 			r = scanradix(
1177eedc3436SMatthew Dillon 			    &scan[i],
1178eedc3436SMatthew Dillon 			    blk,
1179eedc3436SMatthew Dillon 			    radix,
1180eedc3436SMatthew Dillon 			    next_skip - 1,
1181eedc3436SMatthew Dillon 			    vcount,
1182eedc3436SMatthew Dillon 			    dmmax,
1183eedc3436SMatthew Dillon 			    nswdev,
1184eedc3436SMatthew Dillon 			    perdev,
1185eedc3436SMatthew Dillon 			    tab + 4
1186eedc3436SMatthew Dillon 			);
1187eedc3436SMatthew Dillon 			if (r < 0)
1188eedc3436SMatthew Dillon 				break;
1189eedc3436SMatthew Dillon 			blk += radix;
1190eedc3436SMatthew Dillon 		}
1191eedc3436SMatthew Dillon 		if (swapflag > 1) {
1192eedc3436SMatthew Dillon 			printf("%*.*s}\n", TABME);
1193eedc3436SMatthew Dillon 		}
1194eedc3436SMatthew Dillon 	}
1195eedc3436SMatthew Dillon 	return(0);
1196eedc3436SMatthew Dillon }
1197eedc3436SMatthew Dillon 
1198eedc3436SMatthew Dillon 
1199eedc3436SMatthew Dillon /*
1200dea673e9SRodney W. Grimes  * swapmode is based on a program called swapinfo written
1201dea673e9SRodney W. Grimes  * by Kevin Lahey <kml@rokkaku.atl.ga.us>.
1202dea673e9SRodney W. Grimes  */
1203dea673e9SRodney W. Grimes void
1204eedc3436SMatthew Dillon swapmode(void)
1205dea673e9SRodney W. Grimes {
12069c5cdfe0SPeter Wemm 	char *header, *p;
1207eedc3436SMatthew Dillon 	int hlen, nswdev, dmmax;
1208eedc3436SMatthew Dillon 	int i, div, mul, avail, nfree, npfree, used;
1209dea673e9SRodney W. Grimes 	struct swdevt *sw;
1210dea673e9SRodney W. Grimes 	long blocksize, *perdev;
12111cb2c626SDavid Greenman 	struct rlist head;
1212739a189aSJohn Dyson 	struct rlisthdr swaplist;
1213eedc3436SMatthew Dillon 	struct blist	*swapblist = NULL;
12141295400eSDavid Greenman 	u_long ptr;
1215dea673e9SRodney W. Grimes 
1216dea673e9SRodney W. Grimes 	KGET(VM_NSWDEV, nswdev);
1217eedc3436SMatthew Dillon 	KGET(VM_DMMAX, dmmax);	/* PAGE_BSIZE'd or PAGE_SIZE'd depending */
1218eedc3436SMatthew Dillon 	if (!KGET1N(VM_SWAPLIST, &swaplist, sizeof swaplist, "swaplist")) {
1219eedc3436SMatthew Dillon 	    KGET1(VM_SWAPBLIST, &swapblist, sizeof swapblist, "swapblist");
1220eedc3436SMatthew Dillon 	}
1221eedc3436SMatthew Dillon 
1222dea673e9SRodney W. Grimes 	if ((sw = malloc(nswdev * sizeof(*sw))) == NULL ||
12231cb2c626SDavid Greenman 	    (perdev = malloc(nswdev * sizeof(*perdev))) == NULL)
1224d9961cfdSPhilippe Charnier 		errx(1, "malloc");
12251295400eSDavid Greenman 	KGET1(VM_SWDEVT, &ptr, sizeof ptr, "swdevt");
12261295400eSDavid Greenman 	KGET2(ptr, sw, nswdev * sizeof(*sw), "*swdevt");
1227dea673e9SRodney W. Grimes 
1228dea673e9SRodney W. Grimes 	/* Count up swap space. */
1229dea673e9SRodney W. Grimes 	nfree = 0;
1230dea673e9SRodney W. Grimes 	memset(perdev, 0, nswdev * sizeof(*perdev));
1231eedc3436SMatthew Dillon 
1232eedc3436SMatthew Dillon 	if (swapblist) {
1233eedc3436SMatthew Dillon 		/*
1234eedc3436SMatthew Dillon 		 * New swap radix tree (ugh!)
1235eedc3436SMatthew Dillon 		 */
1236eedc3436SMatthew Dillon 		struct blist blcopy = { 0 };
1237eedc3436SMatthew Dillon 		KGET2(swapblist, &blcopy, sizeof(blcopy), "*swapblist");
1238eedc3436SMatthew Dillon 		if (swapflag > 1) {
1239eedc3436SMatthew Dillon 			printf("radix tree: %d/%d/%d blocks, %dK wired\n",
1240eedc3436SMatthew Dillon 				blcopy.bl_free,
1241eedc3436SMatthew Dillon 				blcopy.bl_blocks,
1242eedc3436SMatthew Dillon 				blcopy.bl_radix,
1243eedc3436SMatthew Dillon 				(blcopy.bl_rootblks * sizeof(blmeta_t) + 1023)/
1244eedc3436SMatthew Dillon 				    1024
1245eedc3436SMatthew Dillon 			);
1246eedc3436SMatthew Dillon 		}
1247eedc3436SMatthew Dillon 		scanradix(blcopy.bl_root, 0, blcopy.bl_radix, blcopy.bl_skip, blcopy.bl_rootblks, dmmax, nswdev, perdev, 0);
1248eedc3436SMatthew Dillon 	} else {
1249eedc3436SMatthew Dillon 		/*
1250eedc3436SMatthew Dillon 		 * Old swap
1251eedc3436SMatthew Dillon 		 */
1252eedc3436SMatthew Dillon 		struct rlist *swapptr;
1253eedc3436SMatthew Dillon 
1254739a189aSJohn Dyson 		swapptr = swaplist.rlh_list;
1255739a189aSJohn Dyson 		while (swapptr) {
12561cb2c626SDavid Greenman 			int	top, bottom, next_block;
12571cb2c626SDavid Greenman 
1258739a189aSJohn Dyson 			KGET2(swapptr, &head, sizeof(struct rlist), "swapptr");
12591cb2c626SDavid Greenman 
12601cb2c626SDavid Greenman 			top = head.rl_end;
12611cb2c626SDavid Greenman 			bottom = head.rl_start;
12621cb2c626SDavid Greenman 
12631cb2c626SDavid Greenman 			nfree += top - bottom + 1;
1264dea673e9SRodney W. Grimes 
1265dea673e9SRodney W. Grimes 			/*
1266dea673e9SRodney W. Grimes 			 * Swap space is split up among the configured disks.
1267dea673e9SRodney W. Grimes 			 *
1268dea673e9SRodney W. Grimes 			 * For interleaved swap devices, the first dmmax blocks
1269eedc3436SMatthew Dillon 			 * of swap space some from the first disk, the next
1270eedc3436SMatthew Dillon 			 * dmmax blocks from the next, and so.
1271dea673e9SRodney W. Grimes 			 *
1272dea673e9SRodney W. Grimes 			 * The list of free space joins adjacent free blocks,
1273dea673e9SRodney W. Grimes 			 * ignoring device boundries.  If we want to keep track
1274dea673e9SRodney W. Grimes 			 * of this information per device, we'll just have to
12751cb2c626SDavid Greenman 			 * extract it ourselves.
1276dea673e9SRodney W. Grimes 			 */
12771cb2c626SDavid Greenman 			while (top / dmmax != bottom / dmmax) {
12781cb2c626SDavid Greenman 				next_block = ((bottom + dmmax) / dmmax);
12791cb2c626SDavid Greenman 				perdev[(bottom / dmmax) % nswdev] +=
12801cb2c626SDavid Greenman 					next_block * dmmax - bottom;
12811cb2c626SDavid Greenman 				bottom = next_block * dmmax;
12821cb2c626SDavid Greenman 			}
12831cb2c626SDavid Greenman 			perdev[(bottom / dmmax) % nswdev] +=
12841cb2c626SDavid Greenman 				top - bottom + 1;
1285dea673e9SRodney W. Grimes 
1286739a189aSJohn Dyson 			swapptr = head.rl_next;
1287dea673e9SRodney W. Grimes 		}
1288eedc3436SMatthew Dillon 	}
1289dea673e9SRodney W. Grimes 
1290dea673e9SRodney W. Grimes 	header = getbsize(&hlen, &blocksize);
1291dea673e9SRodney W. Grimes 	if (!totalflag)
1292dea673e9SRodney W. Grimes 		(void)printf("%-11s %*s %8s %8s %8s  %s\n",
1293dea673e9SRodney W. Grimes 		    "Device", hlen, header,
1294dea673e9SRodney W. Grimes 		    "Used", "Avail", "Capacity", "Type");
1295eedc3436SMatthew Dillon 
1296eedc3436SMatthew Dillon 	mul = 1;
1297eedc3436SMatthew Dillon 	if (swapblist) {
1298eedc3436SMatthew Dillon 		if ((div = blocksize / PAGE_SIZE) == 0) {
1299eedc3436SMatthew Dillon 			mul = PAGE_SIZE / blocksize;
1300eedc3436SMatthew Dillon 			div = 1;
1301eedc3436SMatthew Dillon 		}
1302eedc3436SMatthew Dillon 	} else {
1303eedc3436SMatthew Dillon 		if ((div = blocksize / DEV_BSIZE) == 0) {
1304eedc3436SMatthew Dillon 			mul = DEV_BSIZE / blocksize;
1305eedc3436SMatthew Dillon 			div = 1;
1306eedc3436SMatthew Dillon 		}
1307eedc3436SMatthew Dillon 	}
1308eedc3436SMatthew Dillon 
1309dea673e9SRodney W. Grimes 	avail = npfree = 0;
1310dea673e9SRodney W. Grimes 	for (i = 0; i < nswdev; i++) {
1311dea673e9SRodney W. Grimes 		int xsize, xfree;
1312dea673e9SRodney W. Grimes 
131359392fe2SPoul-Henning Kamp 		/*
131459392fe2SPoul-Henning Kamp 		 * Don't report statistics for partitions which have not
131559392fe2SPoul-Henning Kamp 		 * yet been activated via swapon(8).
131659392fe2SPoul-Henning Kamp 		 */
131759392fe2SPoul-Henning Kamp 		if (!(sw[i].sw_flags & SW_FREED))
131859392fe2SPoul-Henning Kamp 			continue;
131959392fe2SPoul-Henning Kamp 
1320dea673e9SRodney W. Grimes 		if (!totalflag)
13219c5cdfe0SPeter Wemm 			if (sw[i].sw_dev != NODEV) {
13229c5cdfe0SPeter Wemm 				p = devname(sw[i].sw_dev, S_IFBLK);
1323dea673e9SRodney W. Grimes 				(void)printf("/dev/%-6s %*d ",
13249c5cdfe0SPeter Wemm 					     p == NULL ? "??" : p,
1325eedc3436SMatthew Dillon 					     hlen, sw[i].sw_nblks * mul / div);
13269c5cdfe0SPeter Wemm 			} else
132764e529eaSJoerg Wunsch 				(void)printf("[NFS swap]  %*d ",
1328eedc3436SMatthew Dillon 					     hlen, sw[i].sw_nblks * mul / div);
1329dea673e9SRodney W. Grimes 
13302df6483fSPoul-Henning Kamp 		/* The first dmmax is never allocated to avoid trashing of
13312df6483fSPoul-Henning Kamp 		 * disklabels
13322df6483fSPoul-Henning Kamp 		 */
13332df6483fSPoul-Henning Kamp 		xsize = sw[i].sw_nblks - dmmax;
1334dea673e9SRodney W. Grimes 		xfree = perdev[i];
1335dea673e9SRodney W. Grimes 		used = xsize - xfree;
1336dea673e9SRodney W. Grimes 		npfree++;
1337dea673e9SRodney W. Grimes 		avail += xsize;
1338dea673e9SRodney W. Grimes 		if (totalflag)
1339dea673e9SRodney W. Grimes 			continue;
1340dea673e9SRodney W. Grimes 		(void)printf("%8d %8d %5.0f%%    %s\n",
1341eedc3436SMatthew Dillon 		    used * mul / div, xfree * mul / div,
1342dea673e9SRodney W. Grimes 		    (double)used / (double)xsize * 100.0,
1343dea673e9SRodney W. Grimes 		    (sw[i].sw_flags & SW_SEQUENTIAL) ?
1344dea673e9SRodney W. Grimes 			     "Sequential" : "Interleaved");
1345dea673e9SRodney W. Grimes 	}
1346dea673e9SRodney W. Grimes 
1347dea673e9SRodney W. Grimes 	/*
1348dea673e9SRodney W. Grimes 	 * If only one partition has been set up via swapon(8), we don't
1349dea673e9SRodney W. Grimes 	 * need to bother with totals.
1350dea673e9SRodney W. Grimes 	 */
1351dea673e9SRodney W. Grimes 	used = avail - nfree;
1352fb59e630SJordan K. Hubbard 	free(sw);
1353fb59e630SJordan K. Hubbard 	free(perdev);
1354dea673e9SRodney W. Grimes 	if (totalflag) {
1355dea673e9SRodney W. Grimes 		(void)printf("%dM/%dM swap space\n", used / 2048, avail / 2048);
1356dea673e9SRodney W. Grimes 		return;
1357dea673e9SRodney W. Grimes 	}
1358dea673e9SRodney W. Grimes 	if (npfree > 1) {
1359dea673e9SRodney W. Grimes 		(void)printf("%-11s %*d %8d %8d %5.0f%%\n",
1360eedc3436SMatthew Dillon 		    "Total", hlen, avail * mul / div, used * mul / div, nfree * mul / div,
1361dea673e9SRodney W. Grimes 		    (double)used / (double)avail * 100.0);
1362dea673e9SRodney W. Grimes 	}
1363dea673e9SRodney W. Grimes }
1364