GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/main.c Lines: 0 206 0.0 %
Date: 2016-12-06 Branches: 0 115 0.0 %

Line Branch Exec Source
1
/* $Id: main.c,v 1.64 2016/01/02 15:02:05 benno Exp $	 */
2
/*
3
 * Copyright (c) 2001, 2007 Can Erkin Acar
4
 * Copyright (c) 2001 Daniel Hartmeier
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 *    - Redistributions of source code must retain the above copyright
12
 *      notice, this list of conditions and the following disclaimer.
13
 *    - Redistributions in binary form must reproduce the above
14
 *      copyright notice, this list of conditions and the following
15
 *      disclaimer in the documentation and/or other materials provided
16
 *      with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 *
31
 */
32
33
#include <sys/types.h>
34
#include <sys/sysctl.h>
35
36
37
#include <ctype.h>
38
#include <curses.h>
39
#include <err.h>
40
#include <errno.h>
41
#include <fcntl.h>
42
#include <limits.h>
43
#include <netdb.h>
44
#include <signal.h>
45
#include <stdio.h>
46
#include <stdlib.h>
47
#include <string.h>
48
#include <stdarg.h>
49
#include <unistd.h>
50
#include <utmp.h>
51
52
#include "engine.h"
53
#include "systat.h"
54
55
#define TIMEPOS 55
56
57
double	dellave;
58
59
kvm_t	*kd;
60
char	*nlistf = NULL;
61
char	*memf = NULL;
62
double	avenrun[3];
63
double	naptime = 5.0;
64
int	verbose = 1;		/* to report kvm read errs */
65
int	nflag = 1;
66
int	ut, hz, stathz;
67
char    hostname[HOST_NAME_MAX+1];
68
WINDOW  *wnd;
69
int	CMDLINE;
70
char	timebuf[26];
71
char	uloadbuf[TIMEPOS];
72
73
74
int  ucount(void);
75
void usage(void);
76
77
/* command prompt */
78
79
void cmd_delay(const char *);
80
void cmd_count(const char *);
81
void cmd_compat(const char *);
82
83
struct command cm_compat = {"Command", cmd_compat};
84
struct command cm_delay = {"Seconds to delay", cmd_delay};
85
struct command cm_count = {"Number of lines to display", cmd_count};
86
87
88
/* display functions */
89
90
int
91
print_header(void)
92
{
93
	time_t now;
94
	int start = dispstart + 1, end = dispstart + maxprint;
95
	char tmpbuf[TIMEPOS];
96
	char header[MAX_LINE_BUF];
97
98
	if (end > num_disp)
99
		end = num_disp;
100
101
	tb_start();
102
103
	if (!paused) {
104
		getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
105
106
		snprintf(uloadbuf, sizeof(uloadbuf),
107
		    "%5d users    Load %.2f %.2f %.2f",
108
		    ucount(), avenrun[0], avenrun[1], avenrun[2]);
109
110
		time(&now);
111
		strlcpy(timebuf, ctime(&now), sizeof(timebuf));
112
	}
113
114
	if (num_disp && (start > 1 || end != num_disp))
115
		snprintf(tmpbuf, sizeof(tmpbuf),
116
		    "%s (%u-%u of %u) %s", uloadbuf, start, end, num_disp,
117
		    paused ? "PAUSED" : "");
118
	else
119
		snprintf(tmpbuf, sizeof(tmpbuf),
120
		    "%s %s", uloadbuf,
121
		    paused ? "PAUSED" : "");
122
123
	snprintf(header, sizeof(header), "%-55s%s", tmpbuf, timebuf);
124
125
	if (rawmode)
126
		printf("\n\n%s\n", header);
127
	else
128
		mvprintw(0, 0, "%s", header);
129
130
	return (1);
131
}
132
133
/* compatibility functions, rearrange later */
134
void
135
error(const char *fmt, ...)
136
{
137
	va_list ap;
138
	char buf[MAX_LINE_BUF];
139
140
	va_start(ap, fmt);
141
	vsnprintf(buf, sizeof buf, fmt, ap);
142
	va_end(ap);
143
144
	message_set(buf);
145
}
146
147
void
148
nlisterr(struct nlist namelist[])
149
{
150
	int i, n;
151
152
	n = 0;
153
	clear();
154
	mvprintw(2, 10, "systat: nlist: can't find following symbols:");
155
	for (i = 0;
156
	    namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
157
		if (namelist[i].n_value == 0)
158
			mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
159
	move(CMDLINE, 0);
160
	clrtoeol();
161
	refresh();
162
	endwin();
163
	exit(1);
164
}
165
166
void
167
die(void)
168
{
169
	if (!rawmode)
170
		endwin();
171
	exit(0);
172
}
173
174
175
int
176
prefix(char *s1, char *s2)
177
{
178
179
	while (*s1 == *s2) {
180
		if (*s1 == '\0')
181
			return (1);
182
		s1++, s2++;
183
	}
184
	return (*s1 == '\0');
185
}
186
187
/* calculate number of users on the system */
188
int
189
ucount(void)
190
{
191
	int nusers = 0;
192
	struct	utmp utmp;
193
194
	if (ut < 0)
195
		return (0);
196
	lseek(ut, (off_t)0, SEEK_SET);
197
	while (read(ut, &utmp, sizeof(utmp)))
198
		if (utmp.ut_name[0] != '\0')
199
			nusers++;
200
201
	return (nusers);
202
}
203
204
/* main program functions */
205
206
void
207
usage(void)
208
{
209
	extern char *__progname;
210
	fprintf(stderr, "usage: %s [-aBbiNn] [-d count] "
211
	    "[-s delay] [-w width] [view] [delay]\n", __progname);
212
	exit(1);
213
}
214
215
void
216
show_view(void)
217
{
218
	if (rawmode)
219
		return;
220
221
	tb_start();
222
	tbprintf("%s %g", curr_view->name, naptime);
223
	tb_end();
224
	message_set(tmp_buf);
225
}
226
227
void
228
add_view_tb(field_view *v)
229
{
230
	if (curr_view == v)
231
		tbprintf("[%s] ", v->name);
232
	else
233
		tbprintf("%s ", v->name);
234
}
235
236
void
237
show_help(void)
238
{
239
	if (rawmode)
240
		return;
241
242
	tb_start();
243
	foreach_view(add_view_tb);
244
	tb_end();
245
	message_set(tmp_buf);
246
}
247
248
void
249
cmd_compat(const char *buf)
250
{
251
	const char *s;
252
253
	if (strcasecmp(buf, "help") == 0) {
254
		show_help();
255
		need_update = 1;
256
		return;
257
	}
258
	if (strcasecmp(buf, "quit") == 0 || strcasecmp(buf, "q") == 0) {
259
		gotsig_close = 1;
260
		return;
261
	}
262
	if (strcasecmp(buf, "stop") == 0) {
263
		paused = 1;
264
		gotsig_alarm = 1;
265
		return;
266
	}
267
	if (strncasecmp(buf, "start", 5) == 0) {
268
		paused = 0;
269
		gotsig_alarm = 1;
270
		cmd_delay(buf + 5);
271
		return;
272
	}
273
274
	for (s = buf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
275
		;
276
	if (*s) {
277
		if (set_view(buf))
278
			error("Invalid/ambiguous view: %s", buf);
279
	} else
280
		cmd_delay(buf);
281
}
282
283
void
284
cmd_delay(const char *buf)
285
{
286
	double del;
287
	del = atof(buf);
288
289
	if (del > 0) {
290
		udelay = (useconds_t)(del * 1000000);
291
		gotsig_alarm = 1;
292
		naptime = del;
293
	}
294
}
295
296
void
297
cmd_count(const char *buf)
298
{
299
	const char *errstr;
300
301
	maxprint = strtonum(buf, 1, lines - HEADER_LINES, &errstr);
302
	if (errstr)
303
		maxprint = lines - HEADER_LINES;
304
}
305
306
307
int
308
keyboard_callback(int ch)
309
{
310
	switch (ch) {
311
	case '?':
312
		/* FALLTHROUGH */
313
	case 'h':
314
		show_help();
315
		need_update = 1;
316
		break;
317
	case CTRL_G:
318
		show_view();
319
		need_update = 1;
320
		break;
321
	case 'l':
322
		command_set(&cm_count, NULL);
323
		break;
324
	case 's':
325
		command_set(&cm_delay, NULL);
326
		break;
327
	case ',':
328
		separate_thousands = !separate_thousands;
329
		gotsig_alarm = 1;
330
		break;
331
	case ':':
332
		command_set(&cm_compat, NULL);
333
		break;
334
	default:
335
		return 0;
336
	};
337
338
	return 1;
339
}
340
341
void
342
initialize(void)
343
{
344
	engine_initialize();
345
346
	initvmstat();
347
	initpigs();
348
	initifstat();
349
	initiostat();
350
	initsensors();
351
	initmembufs();
352
	initnetstat();
353
	initswap();
354
	initpftop();
355
	initpf();
356
	initpool();
357
	initmalloc();
358
	initnfs();
359
	initcpu();
360
}
361
362
void
363
gethz(void)
364
{
365
	struct clockinfo cinf;
366
	size_t  size = sizeof(cinf);
367
	int	mib[2];
368
369
	mib[0] = CTL_KERN;
370
	mib[1] = KERN_CLOCKRATE;
371
	if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
372
		return;
373
	stathz = cinf.stathz;
374
	hz = cinf.hz;
375
}
376
377
int
378
main(int argc, char *argv[])
379
{
380
	char errbuf[_POSIX2_LINE_MAX];
381
	const char *errstr;
382
	extern char *optarg;
383
	extern int optind;
384
	double delay = 5;
385
386
	char *viewstr = NULL;
387
388
	gid_t gid;
389
	int countmax = 0;
390
	int maxlines = 0;
391
392
	int ch;
393
394
	ut = open(_PATH_UTMP, O_RDONLY);
395
	if (ut < 0) {
396
		warn("No utmp");
397
	}
398
399
	kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
400
401
	gid = getgid();
402
	if (setresgid(gid, gid, gid) == -1)
403
		err(1, "setresgid");
404
405
	while ((ch = getopt(argc, argv, "BNabd:ins:w:")) != -1) {
406
		switch (ch) {
407
		case 'a':
408
			maxlines = -1;
409
			break;
410
		case 'B':
411
			averageonly = 1;
412
			if (countmax < 2)
413
				countmax = 2;
414
			/* FALLTHROUGH */
415
		case 'b':
416
			rawmode = 1;
417
			interactive = 0;
418
			break;
419
		case 'd':
420
			countmax = strtonum(optarg, 1, INT_MAX, &errstr);
421
			if (errstr)
422
				errx(1, "-d %s: %s", optarg, errstr);
423
			break;
424
		case 'i':
425
			interactive = 1;
426
			break;
427
		case 'N':
428
			nflag = 0;
429
			break;
430
		case 'n':
431
			/* this is a noop, -n is the default */
432
			nflag = 1;
433
			break;
434
		case 's':
435
			delay = atof(optarg);
436
			if (delay <= 0)
437
				delay = 5;
438
			break;
439
		case 'w':
440
			rawwidth = strtonum(optarg, 1, MAX_LINE_BUF-1, &errstr);
441
			if (errstr)
442
				errx(1, "-w %s: %s", optarg, errstr);
443
			break;
444
		default:
445
			usage();
446
			/* NOTREACHED */
447
		}
448
	}
449
450
	if (kd == NULL)
451
		warnx("kvm_openfiles: %s", errbuf);
452
453
	argc -= optind;
454
	argv += optind;
455
456
	if (argc == 1) {
457
		double del = atof(argv[0]);
458
		if (del == 0)
459
			viewstr = argv[0];
460
		else
461
			delay = del;
462
	} else if (argc == 2) {
463
		viewstr = argv[0];
464
		delay = atof(argv[1]);
465
		if (delay <= 0)
466
			delay = 5;
467
	}
468
469
	udelay = (useconds_t)(delay * 1000000.0);
470
	if (udelay < 1)
471
		udelay = 1;
472
473
	naptime = (double)udelay / 1000000.0;
474
475
	gethostname(hostname, sizeof (hostname));
476
	gethz();
477
478
	initialize();
479
480
	set_order(NULL);
481
	if (viewstr && set_view(viewstr)) {
482
		fprintf(stderr, "Unknown/ambiguous view name: %s\n", viewstr);
483
		return 1;
484
	}
485
486
	if (check_termcap()) {
487
		rawmode = 1;
488
		interactive = 0;
489
	}
490
491
	setup_term(maxlines);
492
493
	if (rawmode && countmax == 0)
494
		countmax = 1;
495
496
	gotsig_alarm = 1;
497
498
	engine_loop(countmax);
499
500
	return 0;
501
}