xref: /original-bsd/usr.bin/vmstat.sparc/main.c (revision b4971bb3)
1 /*
2  * Copyright (c) 1980, 1986, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/device.h>
20 #include <sys/disklabel.h>
21 #include <sys/disk.h>
22 #include <sys/time.h>
23 #include <sys/dkstat.h>
24 #include <sys/ioctl.h>
25 #include <vm/vm.h>
26 
27 #include <ctype.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <kvm.h>
31 #include <limits.h>
32 #include <nlist.h>
33 #include <paths.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38 #include <unistd.h>
39 
40 #include "extern.h"
41 #include "getdev.h"
42 
43 struct nlist nl[] = {
44 	{ "_alldevs" },
45 #define	X_ALLDEVS	0
46 	{ "_boottime" },
47 #define	X_BOOTTIME	1
48 	0
49 };
50 
51 struct dkinfo *dkinfo, **nextdk = &dkinfo;
52 int	ndrives;
53 kvm_t	*kd;
54 
55 void	dkadd __P((u_long, struct device *));
56 char	**dkselect __P((char **));
57 void	getdisks __P((u_long));
58 int	isdk __P((struct device *));
59 
60 #define	INTRSTAT	0x01
61 #define	MEMSTAT		0x02
62 #define	SUMSTAT		0x04
63 #define	VMSTAT		0x08
64 
65 int
66 main(argc, argv)
67 	register int argc;
68 	register char **argv;
69 {
70 	extern int optind;
71 	extern char *optarg;
72 	register int c, todo;
73 	u_int interval;
74 	int reps;
75 	char *memf, *nlistf;
76         char errbuf[_POSIX2_LINE_MAX];
77 
78 	memf = nlistf = NULL;
79 	interval = reps = todo = 0;
80 	while ((c = getopt(argc, argv, "c:iM:mN:sw:")) != EOF) {
81 		switch (c) {
82 		case 'c':
83 			reps = atoi(optarg);
84 			break;
85 		case 'i':
86 			todo |= INTRSTAT;
87 			break;
88 		case 'M':
89 			memf = optarg;
90 			break;
91 		case 'm':
92 			todo |= MEMSTAT;
93 			break;
94 		case 'N':
95 			nlistf = optarg;
96 			break;
97 		case 's':
98 			todo |= SUMSTAT;
99 			break;
100 		case 'w':
101 			interval = atoi(optarg);
102 			break;
103 		case '?':
104 		default:
105 			errexit("usage: vmstat [-ims] [-c count] [-M core] \
106 [-N system] [-w wait] [disks]\n");
107 			/* NOTREACHED */
108 		}
109 	}
110 	argc -= optind;
111 	argv += optind;
112 
113 	if (todo == 0)
114 		todo = VMSTAT;
115 
116 	/*
117 	 * Discard setgid privileges if not the running kernel so that bad
118 	 * guys can't print interesting stuff from kernel memory.
119 	 */
120 	if (nlistf != NULL || memf != NULL)
121 		setgid(getgid());
122 
123         kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
124 	if (kd == 0) {
125 		(void)fprintf(stderr,
126 		    "vmstat: kvm_openfiles: %s\n", errbuf);
127 		exit(1);
128 	}
129 
130 	if ((c = kvm_nlist(kd, nl)) != 0) {
131 		if (c > 0) {
132 			(void)fprintf(stderr,
133 			    "vmstat: undefined symbols: ");
134 			for (c = 0; c < sizeof(nl)/sizeof(nl[0]) - 1; c++)
135 				if (nl[c].n_type == 0)
136 					printf(" %s", nl[c].n_name);
137 			(void)fputc('\n', stderr);
138 		} else
139 			(void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
140 			    kvm_geterr(kd));
141 		exit(1);
142 	}
143 
144 	if (todo & VMSTAT) {
145 		getdev(nl[X_ALLDEVS].n_value, isdk, dkadd);
146 		argv = dkselect(argv);
147 	}
148 
149 #define	BACKWARD_COMPATIBILITY
150 #ifdef	BACKWARD_COMPATIBILITY
151 	if (*argv) {
152 		interval = atoi(*argv);
153 		if (*++argv)
154 			reps = atoi(*argv);
155 	}
156 #endif
157 
158 	if (interval) {
159 		if (!reps)
160 			reps = -1;
161 	} else if (reps)
162 		interval = 1;
163 
164 	if (todo & MEMSTAT)
165 		domem();
166 	if (todo & SUMSTAT)
167 		dosum();
168 	if (todo & INTRSTAT)
169 		dointr();
170 	if (todo & VMSTAT)
171 		dovmstat(interval, reps);
172 	exit(0);
173 }
174 
175 int
176 isdk(dv)
177 	struct device *dv;
178 {
179 
180 	return (dv->dv_class == DV_DISK);
181 }
182 
183 void
184 dkadd(addr, dv)
185 	u_long addr;
186 	struct device *dv;
187 {
188 	register struct dkinfo *dk;
189 	register char *name;
190 
191 	name = dv->dv_xname;
192 	dk = malloc(sizeof *dk);
193 	if (dk == NULL || (dk->dk_name = strdup(name)) == NULL)
194 		errexit("dkadd(%s): malloc: %s\n", name, strerror(errno));
195 	*nextdk = dk;
196 	nextdk = &dk->dk_next;
197 	dk->dk_next = NULL;
198 	dk->dk_sel = 0;
199 	dk->dk_addr = addr;
200 	dk->dk_2c[0] = name[0];
201 	dk->dk_2c[1] = name[strlen(name) - 1];
202 	dk->dk_2c[2] = 0;
203 #ifdef notyet
204 	/*
205 	 * Fill in dk_oxfer so that we can compute deltas next time.
206 	 */
207 	(void)snprintf(buf, sizeof buf, "%s xfer", name);
208 	kread(addr + offsetof(struct dkdevice, dk_xfer),
209 	    &dk->dk_oxfer, sizeof dk->dk_oxfer, buf);
210 #endif
211 }
212 
213 /*
214  * Choose drives to be displayed.  Priority goes to (in order) drives
215  * supplied as arguments, default drives.  If everything isn't filled
216  * in and there are drives not taken care of, display the first few
217  * that fit.
218  */
219 char **
220 dkselect(argv)
221 	char **argv;
222 {
223 	register struct dkinfo *dk;
224 	register char **cpp, *cp;
225 	extern char *defdrives[];
226 #define BACKWARD_COMPATIBILITY
227 
228 	for (; (cp = *argv) != NULL; ++argv) {
229 #ifdef	BACKWARD_COMPATIBILITY
230 		if (isdigit(*cp))
231 			break;
232 #endif
233 		for (dk = dkinfo; dk != NULL; dk = dk->dk_next) {
234 			if (strcmp(dk->dk_name, cp) != 0)
235 				continue;
236 			if (!dk->dk_sel) {
237 				dk->dk_sel = 1;
238 				++ndrives;
239 			}
240 			break;
241 		}
242 	}
243 	for (dk = dkinfo; dk != NULL && ndrives < 4; dk = dk->dk_next) {
244 		if (dk->dk_sel)
245 			continue;
246 		for (cpp = defdrives; (cp = *cpp) != NULL; cpp++)
247 			if (strcmp(dk->dk_name, cp) == 0) {
248 				dk->dk_sel = 1;
249 				++ndrives;
250 				break;
251 			}
252 	}
253 	for (dk = dkinfo; dk != NULL && ndrives < 4; dk = dk->dk_next) {
254 		if (dk->dk_sel)
255 			continue;
256 		dk->dk_sel = 1;
257 		++ndrives;
258 	}
259 	return (argv);
260 }
261 
262 long
263 getuptime()
264 {
265 	static time_t boottime;
266 	time_t now, uptime;
267 
268 	if (boottime == 0)
269 		kread(nl[X_BOOTTIME].n_value, &boottime, sizeof boottime,
270 		    "boottime");
271 	(void)time(&now);
272 	uptime = now - boottime;
273 	if (uptime <= 0 || uptime > 60*60*24*365*10) {
274 		(void)fprintf(stderr,
275 		    "vmstat: time makes no sense; namelist must be wrong.\n");
276 		exit(1);
277 	}
278 	return (uptime);
279 }
280