xref: /csrg-svn/usr.bin/vmstat.sparc/main.c (revision 62431)
160194Storek /*
2*62431Sbostic  * Copyright (c) 1980, 1986, 1991, 1993
3*62431Sbostic  *	The Regents of the University of California.  All rights reserved.
460194Storek  *
560194Storek  * %sccs.include.redist.c%
660194Storek  */
760194Storek 
860194Storek #ifndef lint
9*62431Sbostic static char copyright[] =
10*62431Sbostic "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
11*62431Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1260194Storek #endif /* not lint */
1360194Storek 
1460194Storek #ifndef lint
15*62431Sbostic static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 06/06/93";
1660194Storek #endif /* not lint */
1760194Storek 
1860194Storek #include <sys/param.h>
1960194Storek #include <sys/device.h>
2060194Storek #include <sys/disklabel.h>
2160194Storek #include <sys/disk.h>
2260194Storek #include <sys/time.h>
2360194Storek #include <sys/dkstat.h>
2460194Storek #include <sys/ioctl.h>
2560194Storek #include <vm/vm.h>
2660194Storek 
2760194Storek #include <ctype.h>
2860194Storek #include <errno.h>
2960194Storek #include <fcntl.h>
3060194Storek #include <kvm.h>
3160194Storek #include <limits.h>
3260194Storek #include <nlist.h>
3360194Storek #include <paths.h>
3460194Storek #include <stdio.h>
3560194Storek #include <stdlib.h>
3660194Storek #include <string.h>
3760194Storek #include <time.h>
3860194Storek #include <unistd.h>
3960194Storek 
4060194Storek #include "extern.h"
4160194Storek #include "getdev.h"
4260194Storek 
4360194Storek struct nlist nl[] = {
4460194Storek 	{ "_alldevs" },
4560194Storek #define	X_ALLDEVS	0
4660194Storek 	{ "_boottime" },
4760194Storek #define	X_BOOTTIME	1
4860194Storek 	0
4960194Storek };
5060194Storek 
5160194Storek struct dkinfo *dkinfo, **nextdk = &dkinfo;
5260194Storek int	ndrives;
5360194Storek kvm_t	*kd;
5460194Storek 
5560194Storek void	dkadd __P((u_long, struct device *));
5660194Storek char	**dkselect __P((char **));
5760194Storek void	getdisks __P((u_long));
5860194Storek int	isdk __P((struct device *));
5960194Storek 
6060194Storek #define	INTRSTAT	0x01
6160194Storek #define	MEMSTAT		0x02
6260194Storek #define	SUMSTAT		0x04
6360194Storek #define	VMSTAT		0x08
6460194Storek 
6560194Storek int
main(argc,argv)6660194Storek main(argc, argv)
6760194Storek 	register int argc;
6860194Storek 	register char **argv;
6960194Storek {
7060194Storek 	extern int optind;
7160194Storek 	extern char *optarg;
7260194Storek 	register int c, todo;
7360194Storek 	u_int interval;
7460194Storek 	int reps;
7560194Storek 	char *memf, *nlistf;
7660194Storek         char errbuf[_POSIX2_LINE_MAX];
7760194Storek 
7860194Storek 	memf = nlistf = NULL;
7960194Storek 	interval = reps = todo = 0;
8060194Storek 	while ((c = getopt(argc, argv, "c:iM:mN:sw:")) != EOF) {
8160194Storek 		switch (c) {
8260194Storek 		case 'c':
8360194Storek 			reps = atoi(optarg);
8460194Storek 			break;
8560194Storek 		case 'i':
8660194Storek 			todo |= INTRSTAT;
8760194Storek 			break;
8860194Storek 		case 'M':
8960194Storek 			memf = optarg;
9060194Storek 			break;
9160194Storek 		case 'm':
9260194Storek 			todo |= MEMSTAT;
9360194Storek 			break;
9460194Storek 		case 'N':
9560194Storek 			nlistf = optarg;
9660194Storek 			break;
9760194Storek 		case 's':
9860194Storek 			todo |= SUMSTAT;
9960194Storek 			break;
10060194Storek 		case 'w':
10160194Storek 			interval = atoi(optarg);
10260194Storek 			break;
10360194Storek 		case '?':
10460194Storek 		default:
10560194Storek 			errexit("usage: vmstat [-ims] [-c count] [-M core] \
10660194Storek [-N system] [-w wait] [disks]\n");
10760194Storek 			/* NOTREACHED */
10860194Storek 		}
10960194Storek 	}
11060194Storek 	argc -= optind;
11160194Storek 	argv += optind;
11260194Storek 
11360194Storek 	if (todo == 0)
11460194Storek 		todo = VMSTAT;
11560194Storek 
11660194Storek 	/*
11760194Storek 	 * Discard setgid privileges if not the running kernel so that bad
11860194Storek 	 * guys can't print interesting stuff from kernel memory.
11960194Storek 	 */
12060194Storek 	if (nlistf != NULL || memf != NULL)
12160194Storek 		setgid(getgid());
12260194Storek 
12360194Storek         kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
12460194Storek 	if (kd == 0) {
12560194Storek 		(void)fprintf(stderr,
12660194Storek 		    "vmstat: kvm_openfiles: %s\n", errbuf);
12760194Storek 		exit(1);
12860194Storek 	}
12960194Storek 
13060194Storek 	if ((c = kvm_nlist(kd, nl)) != 0) {
13160194Storek 		if (c > 0) {
13260194Storek 			(void)fprintf(stderr,
13360194Storek 			    "vmstat: undefined symbols: ");
13460194Storek 			for (c = 0; c < sizeof(nl)/sizeof(nl[0]) - 1; c++)
13560194Storek 				if (nl[c].n_type == 0)
13660194Storek 					printf(" %s", nl[c].n_name);
13760194Storek 			(void)fputc('\n', stderr);
13860194Storek 		} else
13960194Storek 			(void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
14060194Storek 			    kvm_geterr(kd));
14160194Storek 		exit(1);
14260194Storek 	}
14360194Storek 
14460194Storek 	if (todo & VMSTAT) {
14560194Storek 		getdev(nl[X_ALLDEVS].n_value, isdk, dkadd);
14660194Storek 		argv = dkselect(argv);
14760194Storek 	}
14860194Storek 
14960194Storek #define	BACKWARD_COMPATIBILITY
15060194Storek #ifdef	BACKWARD_COMPATIBILITY
15160194Storek 	if (*argv) {
15260194Storek 		interval = atoi(*argv);
15360194Storek 		if (*++argv)
15460194Storek 			reps = atoi(*argv);
15560194Storek 	}
15660194Storek #endif
15760194Storek 
15860194Storek 	if (interval) {
15960194Storek 		if (!reps)
16060194Storek 			reps = -1;
16160194Storek 	} else if (reps)
16260194Storek 		interval = 1;
16360194Storek 
16460194Storek 	if (todo & MEMSTAT)
16560194Storek 		domem();
16660194Storek 	if (todo & SUMSTAT)
16760194Storek 		dosum();
16860194Storek 	if (todo & INTRSTAT)
16960194Storek 		dointr();
17060194Storek 	if (todo & VMSTAT)
17160194Storek 		dovmstat(interval, reps);
17260194Storek 	exit(0);
17360194Storek }
17460194Storek 
17560194Storek int
isdk(dv)17660194Storek isdk(dv)
17760194Storek 	struct device *dv;
17860194Storek {
17960194Storek 
18060194Storek 	return (dv->dv_class == DV_DISK);
18160194Storek }
18260194Storek 
18360194Storek void
dkadd(addr,dv)18460194Storek dkadd(addr, dv)
18560194Storek 	u_long addr;
18660194Storek 	struct device *dv;
18760194Storek {
18860194Storek 	register struct dkinfo *dk;
18960194Storek 	register char *name;
19060194Storek 
19160194Storek 	name = dv->dv_xname;
19260194Storek 	dk = malloc(sizeof *dk);
19360194Storek 	if (dk == NULL || (dk->dk_name = strdup(name)) == NULL)
19460194Storek 		errexit("dkadd(%s): malloc: %s\n", name, strerror(errno));
19560194Storek 	*nextdk = dk;
19660194Storek 	nextdk = &dk->dk_next;
19760194Storek 	dk->dk_next = NULL;
19860194Storek 	dk->dk_sel = 0;
19960194Storek 	dk->dk_addr = addr;
20060194Storek 	dk->dk_2c[0] = name[0];
20160194Storek 	dk->dk_2c[1] = name[strlen(name) - 1];
20260194Storek 	dk->dk_2c[2] = 0;
20360194Storek #ifdef notyet
20460194Storek 	/*
20560194Storek 	 * Fill in dk_oxfer so that we can compute deltas next time.
20660194Storek 	 */
20760194Storek 	(void)snprintf(buf, sizeof buf, "%s xfer", name);
20860194Storek 	kread(addr + offsetof(struct dkdevice, dk_xfer),
20960194Storek 	    &dk->dk_oxfer, sizeof dk->dk_oxfer, buf);
21060194Storek #endif
21160194Storek }
21260194Storek 
21360194Storek /*
21460194Storek  * Choose drives to be displayed.  Priority goes to (in order) drives
21560194Storek  * supplied as arguments, default drives.  If everything isn't filled
21660194Storek  * in and there are drives not taken care of, display the first few
21760194Storek  * that fit.
21860194Storek  */
21960194Storek char **
dkselect(argv)22060194Storek dkselect(argv)
22160194Storek 	char **argv;
22260194Storek {
22360194Storek 	register struct dkinfo *dk;
22460194Storek 	register char **cpp, *cp;
22560194Storek 	extern char *defdrives[];
22660194Storek #define BACKWARD_COMPATIBILITY
22760194Storek 
22860194Storek 	for (; (cp = *argv) != NULL; ++argv) {
22960194Storek #ifdef	BACKWARD_COMPATIBILITY
23060194Storek 		if (isdigit(*cp))
23160194Storek 			break;
23260194Storek #endif
23360194Storek 		for (dk = dkinfo; dk != NULL; dk = dk->dk_next) {
23460194Storek 			if (strcmp(dk->dk_name, cp) != 0)
23560194Storek 				continue;
23660194Storek 			if (!dk->dk_sel) {
23760194Storek 				dk->dk_sel = 1;
23860194Storek 				++ndrives;
23960194Storek 			}
24060194Storek 			break;
24160194Storek 		}
24260194Storek 	}
24360194Storek 	for (dk = dkinfo; dk != NULL && ndrives < 4; dk = dk->dk_next) {
24460194Storek 		if (dk->dk_sel)
24560194Storek 			continue;
24660194Storek 		for (cpp = defdrives; (cp = *cpp) != NULL; cpp++)
24760194Storek 			if (strcmp(dk->dk_name, cp) == 0) {
24860194Storek 				dk->dk_sel = 1;
24960194Storek 				++ndrives;
25060194Storek 				break;
25160194Storek 			}
25260194Storek 	}
25360194Storek 	for (dk = dkinfo; dk != NULL && ndrives < 4; dk = dk->dk_next) {
25460194Storek 		if (dk->dk_sel)
25560194Storek 			continue;
25660194Storek 		dk->dk_sel = 1;
25760194Storek 		++ndrives;
25860194Storek 	}
25960194Storek 	return (argv);
26060194Storek }
26160194Storek 
26260194Storek long
getuptime()26360194Storek getuptime()
26460194Storek {
26560194Storek 	static time_t boottime;
26660194Storek 	time_t now, uptime;
26760194Storek 
26860194Storek 	if (boottime == 0)
26960194Storek 		kread(nl[X_BOOTTIME].n_value, &boottime, sizeof boottime,
27060194Storek 		    "boottime");
27160194Storek 	(void)time(&now);
27260194Storek 	uptime = now - boottime;
27360194Storek 	if (uptime <= 0 || uptime > 60*60*24*365*10) {
27460194Storek 		(void)fprintf(stderr,
27560194Storek 		    "vmstat: time makes no sense; namelist must be wrong.\n");
27660194Storek 		exit(1);
27760194Storek 	}
27860194Storek 	return (uptime);
27960194Storek }
280