GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/main.c Lines: 0 215 0.0 %
Date: 2017-11-07 Branches: 0 110 0.0 %

Line Branch Exec Source
1
/* $Id: main.c,v 1.66 2016/10/13 11:22:46 otto 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 (80 - 8 - 20 - 1)
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
		char *ctim;
105
106
		getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
107
108
		snprintf(uloadbuf, sizeof(uloadbuf),
109
		    "%4d users Load %.2f %.2f %.2f",
110
		    ucount(), avenrun[0], avenrun[1], avenrun[2]);
111
112
		time(&now);
113
		ctim = ctime(&now);
114
		ctim[11+8] = '\0';
115
		strlcpy(timebuf, ctim + 11, sizeof(timebuf));
116
	}
117
118
	if (num_disp && (start > 1 || end != num_disp))
119
		snprintf(tmpbuf, sizeof(tmpbuf),
120
		    "%s (%u-%u of %u) %s", uloadbuf, start, end, num_disp,
121
		    paused ? "PAUSED" : "");
122
	else
123
		snprintf(tmpbuf, sizeof(tmpbuf),
124
		    "%s %s", uloadbuf,
125
		    paused ? "PAUSED" : "");
126
127
	snprintf(header, sizeof(header), "%-*s %19.19s %s", TIMEPOS - 1,
128
	    tmpbuf, hostname, timebuf);
129
130
	if (rawmode)
131
		printf("\n\n%s\n", header);
132
	else
133
		mvprintw(0, 0, "%s", header);
134
135
	return (1);
136
}
137
138
/* compatibility functions, rearrange later */
139
void
140
error(const char *fmt, ...)
141
{
142
	va_list ap;
143
	char buf[MAX_LINE_BUF];
144
145
	va_start(ap, fmt);
146
	vsnprintf(buf, sizeof buf, fmt, ap);
147
	va_end(ap);
148
149
	message_set(buf);
150
}
151
152
void
153
nlisterr(struct nlist namelist[])
154
{
155
	int i, n;
156
157
	n = 0;
158
	clear();
159
	mvprintw(2, 10, "systat: nlist: can't find following symbols:");
160
	for (i = 0;
161
	    namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
162
		if (namelist[i].n_value == 0)
163
			mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
164
	move(CMDLINE, 0);
165
	clrtoeol();
166
	refresh();
167
	endwin();
168
	exit(1);
169
}
170
171
void
172
die(void)
173
{
174
	if (!rawmode)
175
		endwin();
176
	exit(0);
177
}
178
179
180
int
181
prefix(char *s1, char *s2)
182
{
183
184
	while (*s1 == *s2) {
185
		if (*s1 == '\0')
186
			return (1);
187
		s1++, s2++;
188
	}
189
	return (*s1 == '\0');
190
}
191
192
/* calculate number of users on the system */
193
int
194
ucount(void)
195
{
196
	int nusers = 0;
197
	struct	utmp utmp;
198
199
	if (ut < 0)
200
		return (0);
201
	lseek(ut, (off_t)0, SEEK_SET);
202
	while (read(ut, &utmp, sizeof(utmp)))
203
		if (utmp.ut_name[0] != '\0')
204
			nusers++;
205
206
	return (nusers);
207
}
208
209
/* main program functions */
210
211
void
212
usage(void)
213
{
214
	extern char *__progname;
215
	fprintf(stderr, "usage: %s [-aBbiNn] [-d count] "
216
	    "[-s delay] [-w width] [view] [delay]\n", __progname);
217
	exit(1);
218
}
219
220
void
221
show_view(void)
222
{
223
	if (rawmode)
224
		return;
225
226
	tb_start();
227
	tbprintf("%s %g", curr_view->name, naptime);
228
	tb_end();
229
	message_set(tmp_buf);
230
}
231
232
void
233
add_view_tb(field_view *v)
234
{
235
	if (curr_view == v)
236
		tbprintf("[%s] ", v->name);
237
	else
238
		tbprintf("%s ", v->name);
239
}
240
241
void
242
show_help(void)
243
{
244
	if (rawmode)
245
		return;
246
247
	tb_start();
248
	foreach_view(add_view_tb);
249
	tb_end();
250
	message_set(tmp_buf);
251
}
252
253
void
254
cmd_compat(const char *buf)
255
{
256
	const char *s;
257
258
	if (strcasecmp(buf, "help") == 0) {
259
		show_help();
260
		need_update = 1;
261
		return;
262
	}
263
	if (strcasecmp(buf, "quit") == 0 || strcasecmp(buf, "q") == 0) {
264
		gotsig_close = 1;
265
		return;
266
	}
267
	if (strcasecmp(buf, "stop") == 0) {
268
		paused = 1;
269
		gotsig_alarm = 1;
270
		return;
271
	}
272
	if (strncasecmp(buf, "start", 5) == 0) {
273
		paused = 0;
274
		gotsig_alarm = 1;
275
		cmd_delay(buf + 5);
276
		return;
277
	}
278
279
	for (s = buf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
280
		;
281
	if (*s) {
282
		if (set_view(buf))
283
			error("Invalid/ambiguous view: %s", buf);
284
	} else
285
		cmd_delay(buf);
286
}
287
288
void
289
cmd_delay(const char *buf)
290
{
291
	double del;
292
	del = atof(buf);
293
294
	if (del > 0) {
295
		udelay = (useconds_t)(del * 1000000);
296
		gotsig_alarm = 1;
297
		naptime = del;
298
	}
299
}
300
301
void
302
cmd_count(const char *buf)
303
{
304
	const char *errstr;
305
306
	maxprint = strtonum(buf, 1, lines - HEADER_LINES, &errstr);
307
	if (errstr)
308
		maxprint = lines - HEADER_LINES;
309
}
310
311
312
int
313
keyboard_callback(int ch)
314
{
315
	switch (ch) {
316
	case '?':
317
		/* FALLTHROUGH */
318
	case 'h':
319
		show_help();
320
		need_update = 1;
321
		break;
322
	case CTRL_G:
323
		show_view();
324
		need_update = 1;
325
		break;
326
	case 'l':
327
		command_set(&cm_count, NULL);
328
		break;
329
	case 's':
330
		command_set(&cm_delay, NULL);
331
		break;
332
	case ',':
333
		separate_thousands = !separate_thousands;
334
		gotsig_alarm = 1;
335
		break;
336
	case ':':
337
		command_set(&cm_compat, NULL);
338
		break;
339
	default:
340
		return 0;
341
	};
342
343
	return 1;
344
}
345
346
void
347
initialize(void)
348
{
349
	engine_initialize();
350
351
	initvmstat();
352
	initpigs();
353
	initifstat();
354
	initiostat();
355
	initsensors();
356
	initmembufs();
357
	initnetstat();
358
	initswap();
359
	initpftop();
360
	initpf();
361
	initpool();
362
	initmalloc();
363
	initnfs();
364
	initcpu();
365
}
366
367
void
368
gethz(void)
369
{
370
	struct clockinfo cinf;
371
	size_t  size = sizeof(cinf);
372
	int	mib[2];
373
374
	mib[0] = CTL_KERN;
375
	mib[1] = KERN_CLOCKRATE;
376
	if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
377
		return;
378
	stathz = cinf.stathz;
379
	hz = cinf.hz;
380
}
381
382
int
383
main(int argc, char *argv[])
384
{
385
	char errbuf[_POSIX2_LINE_MAX];
386
	const char *errstr;
387
	extern char *optarg;
388
	extern int optind;
389
	double delay = 5;
390
391
	char *viewstr = NULL;
392
393
	gid_t gid;
394
	int countmax = 0;
395
	int maxlines = 0;
396
397
	int ch;
398
399
	ut = open(_PATH_UTMP, O_RDONLY);
400
	if (ut < 0) {
401
		warn("No utmp");
402
	}
403
404
	kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
405
406
	gid = getgid();
407
	if (setresgid(gid, gid, gid) == -1)
408
		err(1, "setresgid");
409
410
	while ((ch = getopt(argc, argv, "BNabd:ins:w:")) != -1) {
411
		switch (ch) {
412
		case 'a':
413
			maxlines = -1;
414
			break;
415
		case 'B':
416
			averageonly = 1;
417
			if (countmax < 2)
418
				countmax = 2;
419
			/* FALLTHROUGH */
420
		case 'b':
421
			rawmode = 1;
422
			interactive = 0;
423
			break;
424
		case 'd':
425
			countmax = strtonum(optarg, 1, INT_MAX, &errstr);
426
			if (errstr)
427
				errx(1, "-d %s: %s", optarg, errstr);
428
			break;
429
		case 'i':
430
			interactive = 1;
431
			break;
432
		case 'N':
433
			nflag = 0;
434
			break;
435
		case 'n':
436
			/* this is a noop, -n is the default */
437
			nflag = 1;
438
			break;
439
		case 's':
440
			delay = atof(optarg);
441
			if (delay <= 0)
442
				delay = 5;
443
			break;
444
		case 'w':
445
			rawwidth = strtonum(optarg, 1, MAX_LINE_BUF-1, &errstr);
446
			if (errstr)
447
				errx(1, "-w %s: %s", optarg, errstr);
448
			break;
449
		default:
450
			usage();
451
			/* NOTREACHED */
452
		}
453
	}
454
455
	if (kd == NULL)
456
		warnx("kvm_openfiles: %s", errbuf);
457
458
	argc -= optind;
459
	argv += optind;
460
461
	if (argc == 1) {
462
		double del = atof(argv[0]);
463
		if (del == 0)
464
			viewstr = argv[0];
465
		else
466
			delay = del;
467
	} else if (argc == 2) {
468
		viewstr = argv[0];
469
		delay = atof(argv[1]);
470
		if (delay <= 0)
471
			delay = 5;
472
	}
473
474
	udelay = (useconds_t)(delay * 1000000.0);
475
	if (udelay < 1)
476
		udelay = 1;
477
478
	naptime = (double)udelay / 1000000.0;
479
480
	gethostname(hostname, sizeof (hostname));
481
	gethz();
482
483
	initialize();
484
485
	set_order(NULL);
486
	if (viewstr && set_view(viewstr)) {
487
		fprintf(stderr, "Unknown/ambiguous view name: %s\n", viewstr);
488
		return 1;
489
	}
490
491
	if (check_termcap()) {
492
		rawmode = 1;
493
		interactive = 0;
494
	}
495
496
	setup_term(maxlines);
497
498
	if (rawmode && countmax == 0)
499
		countmax = 1;
500
501
	gotsig_alarm = 1;
502
503
	engine_loop(countmax);
504
505
	return 0;
506
}