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

Line Branch Exec Source
1
/*	$OpenBSD: pigs.c,v 1.30 2015/09/12 15:59:36 deraadt Exp $	*/
2
/*	$NetBSD: pigs.c,v 1.3 1995/04/29 05:54:50 cgd Exp $	*/
3
4
/*-
5
 * Copyright (c) 1980, 1992, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
/*
34
 * Pigs display from Bill Reeves at Lucasfilm
35
 */
36
37
#include <sys/param.h>	/* MAXCOMLEN */
38
#include <sys/signal.h>
39
#include <sys/proc.h>
40
#include <sys/resource.h>
41
#include <sys/sched.h>
42
#include <sys/sysctl.h>
43
#include <sys/time.h>
44
45
#include <curses.h>
46
#include <math.h>
47
#include <pwd.h>
48
#include <err.h>
49
#include <stdlib.h>
50
#include <string.h>
51
52
#include "systat.h"
53
54
int compar(const void *, const void *);
55
void print_pg(void);
56
int read_pg(void);
57
int select_pg(void);
58
void showpigs(int k);
59
60
static struct kinfo_proc *procbase = NULL;
61
static int nproc, pigs_cnt, *pb_indices = NULL;
62
static int onproc = -1;
63
64
static long stime[CPUSTATES];
65
static double  lccpu;
66
struct loadavg sysload;
67
68
69
70
field_def fields_pg[] = {
71
	{"USER", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
72
	{"NAME", 10, 24, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
73
	{"PID", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
74
	{"CPU", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
75
	{"", 30, 60, 1, FLD_ALIGN_BAR, -1, 0, 0, 100},
76
};
77
78
#define FLD_PG_USER	FIELD_ADDR(fields_pg,0)
79
#define FLD_PG_NAME	FIELD_ADDR(fields_pg,1)
80
#define FLD_PG_PID	FIELD_ADDR(fields_pg,2)
81
#define FLD_PG_VALUE	FIELD_ADDR(fields_pg,3)
82
#define FLD_PG_BAR	FIELD_ADDR(fields_pg,4)
83
84
/* Define views */
85
field_def *view_pg_0[] = {
86
	FLD_PG_PID, FLD_PG_USER, FLD_PG_NAME, FLD_PG_VALUE, FLD_PG_BAR, NULL
87
};
88
89
90
/* Define view managers */
91
struct view_manager pigs_mgr = {
92
	"Pigs", select_pg, read_pg, NULL, print_header,
93
	print_pg, keyboard_callback, NULL, NULL
94
};
95
96
field_view views_pg[] = {
97
	{view_pg_0, "pigs", '5', &pigs_mgr},
98
	{NULL, NULL, 0, NULL}
99
};
100
101
int	fscale;
102
103
#define pctdouble(p) ((double)(p) / fscale)
104
105
typedef long pctcpu;
106
107
int
108
select_pg(void)
109
{
110
	int mib[] = { CTL_KERN, KERN_FSCALE };
111
	size_t size = sizeof(fscale);
112
113
        if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
114
            &fscale, &size, NULL, 0) < 0)
115
                return (-1);
116
	num_disp = pigs_cnt;
117
	return (0);
118
}
119
120
121
int
122
getprocs(void)
123
{
124
	size_t size;
125
	int mib[6] = {CTL_KERN, KERN_PROC, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc), 0};
126
127
	int st;
128
129
	free(procbase);
130
	procbase = NULL;
131
132
	st = sysctl(mib, 6, NULL, &size, NULL, 0);
133
	if (st == -1)
134
		return (1);
135
136
	size = 5 * size / 4;		/* extra slop */
137
	if ((procbase = malloc(size + 1)) == NULL)
138
		return (1);
139
140
	mib[5] = (int)(size / sizeof(struct kinfo_proc));
141
	st = sysctl(mib, 6, procbase, &size, NULL, 0);
142
	if (st == -1)
143
		return (1);
144
145
	nproc = (int)(size / sizeof(struct kinfo_proc));
146
	return (0);
147
}
148
149
150
int
151
read_pg(void)
152
{
153
	static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
154
	long ctimes[CPUSTATES];
155
	double t;
156
	int i, k;
157
	size_t size;
158
159
	num_disp = pigs_cnt = 0;
160
161
	if (getprocs()) {
162
		error("Failed to read process info!");
163
		return 1;
164
	}
165
166
	if (nproc > onproc) {
167
		int *p;
168
		p = reallocarray(pb_indices, nproc + 1, sizeof(int));
169
		if (p == NULL) {
170
			error("Out of Memory!");
171
			return 1;
172
		}
173
		pb_indices = p;
174
		onproc = nproc;
175
	}
176
177
	memset(&procbase[nproc], 0, sizeof(*procbase));
178
179
	for (i = 0; i <= nproc; i++)
180
		pb_indices[i] = i;
181
182
	/*
183
	 * and for the imaginary "idle" process
184
	 */
185
	size = sizeof(ctimes);
186
	sysctl(cp_time_mib, 2, &ctimes, &size, NULL, 0);
187
188
	t = 0;
189
	for (i = 0; i < CPUSTATES; i++)
190
		t += ctimes[i] - stime[i];
191
	if (t == 0.0)
192
		t = 1.0;
193
194
	procbase[nproc].p_pctcpu = (ctimes[CP_IDLE] - stime[CP_IDLE]) / t / pctdouble(1);
195
	for (i = 0; i < CPUSTATES; i++)
196
		stime[i] = ctimes[i];
197
198
	qsort(pb_indices, nproc + 1, sizeof (int), compar);
199
200
	pigs_cnt = 0;
201
	for (k = 0; k < nproc + 1; k++) {
202
		int j = pb_indices[k];
203
		if (pctdouble(procbase[j].p_pctcpu) < 0.01)
204
			break;
205
		pigs_cnt++;
206
	}
207
208
	num_disp = pigs_cnt;
209
	return 0;
210
}
211
212
213
void
214
print_pg(void)
215
{
216
	int n, count = 0;
217
218
	for (n = dispstart; n < num_disp; n++) {
219
		showpigs(pb_indices[n]);
220
		count++;
221
		if (maxprint > 0 && count >= maxprint)
222
			break;
223
	}
224
}
225
226
int
227
initpigs(void)
228
{
229
	static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
230
	static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
231
	static int ccpu_mib[] = { CTL_KERN, KERN_CCPU };
232
	field_view *v;
233
	size_t size;
234
	fixpt_t ccpu;
235
236
	size = sizeof(stime);
237
	sysctl(cp_time_mib, 2, &stime, &size, NULL, 0);
238
239
	size = sizeof(sysload);
240
	sysctl(sysload_mib, 2, &sysload, &size, NULL, 0);
241
242
	size = sizeof(ccpu);
243
	sysctl(ccpu_mib, 2, &ccpu, &size, NULL, 0);
244
245
	lccpu = log((double) ccpu / sysload.fscale);
246
247
	for (v = views_pg; v->name != NULL; v++)
248
		add_view(v);
249
250
	return(1);
251
}
252
253
void
254
showpigs(int k)
255
{
256
	struct kinfo_proc *kp;
257
	double value;
258
	char *uname, *pname;
259
260
	if (procbase == NULL)
261
		return;
262
263
	value = pctdouble(procbase[k].p_pctcpu) * 100;
264
265
	kp = &procbase[k];
266
	if (kp->p_comm[0] == '\0') {
267
		uname = "";
268
		pname = "<idle>";
269
	} else {
270
		uname = user_from_uid(kp->p_uid, 0);
271
		pname = kp->p_comm;
272
		print_fld_uint(FLD_PG_PID, kp->p_pid);
273
	}
274
275
	tb_start();
276
	tbprintf("%.2f", value);
277
	print_fld_tb(FLD_PG_VALUE);
278
279
	print_fld_str(FLD_PG_NAME, pname);
280
	print_fld_str(FLD_PG_USER, uname);
281
	print_fld_bar(FLD_PG_BAR, value);
282
283
	end_line();
284
}
285
286
287
int
288
compar(const void *a, const void *b)
289
{
290
	int i1 = *((int *)a);
291
	int i2 = *((int *)b);
292
293
	return procbase[i1].p_pctcpu >
294
		procbase[i2].p_pctcpu ? -1 : 1;
295
}
296