1205408Srdivacky/*-
2205408Srdivacky * Copyright (c) 1980, 1992, 1993
3205408Srdivacky *	The Regents of the University of California.  All rights reserved.
4205408Srdivacky *
5205408Srdivacky * Redistribution and use in source and binary forms, with or without
6205408Srdivacky * modification, are permitted provided that the following conditions
7205408Srdivacky * are met:
8205408Srdivacky * 1. Redistributions of source code must retain the above copyright
9205408Srdivacky *    notice, this list of conditions and the following disclaimer.
10205408Srdivacky * 2. Redistributions in binary form must reproduce the above copyright
11205408Srdivacky *    notice, this list of conditions and the following disclaimer in the
12205408Srdivacky *    documentation and/or other materials provided with the distribution.
13205408Srdivacky * 4. Neither the name of the University nor the names of its contributors
14205408Srdivacky *    may be used to endorse or promote products derived from this software
15205408Srdivacky *    without specific prior written permission.
16205408Srdivacky *
17249423Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18218893Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19205408Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20205408Srdivacky * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21205408Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22205408Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23205408Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24218893Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25218893Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26218893Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27226633Sdim * SUCH DAMAGE.
28243830Sdim */
29243830Sdim
30218893Sdim#if 0
31218893Sdim#ifndef lint
32243830Sdimstatic char sccsid[] = "@(#)pigs.c	8.2 (Berkeley) 9/23/93";
33218893Sdim#endif /* not lint */
34218893Sdim#endif
35218893Sdim
36218893Sdim#include <sys/cdefs.h>
37218893Sdim__FBSDID("$FreeBSD$");
38226633Sdim
39218893Sdim/*
40218893Sdim * Pigs display from Bill Reeves at Lucasfilm
41249423Sdim */
42234353Sdim
43249423Sdim#include <sys/param.h>
44205408Srdivacky#include <sys/proc.h>
45205408Srdivacky#include <sys/sysctl.h>
46226633Sdim#include <sys/time.h>
47239462Sdim#include <sys/user.h>
48226633Sdim
49226633Sdim#include <curses.h>
50226633Sdim#include <math.h>
51234353Sdim#include <pwd.h>
52234353Sdim#include <stdlib.h>
53234353Sdim
54234353Sdim#include "systat.h"
55234353Sdim#include "extern.h"
56234353Sdim
57234353Sdimint compar(const void *, const void *);
58243830Sdim
59234353Sdimstatic int nproc;
60234353Sdimstatic struct p_times {
61234353Sdim	float pt_pctcpu;
62234353Sdim	struct kinfo_proc *pt_kp;
63234353Sdim} *pt;
64234353Sdim
65234353Sdimstatic int    fscale;
66234353Sdimstatic double  lccpu;
67234353Sdim
68234353SdimWINDOW *
69234353Sdimopenpigs(void)
70234353Sdim{
71234353Sdim	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
72234353Sdim}
73234353Sdim
74234353Sdimvoid
75234353Sdimclosepigs(WINDOW *w)
76234353Sdim{
77234353Sdim	if (w == NULL)
78234353Sdim		return;
79234353Sdim	wclear(w);
80234353Sdim	wrefresh(w);
81234353Sdim	delwin(w);
82234353Sdim}
83234353Sdim
84234353Sdimvoid
85234353Sdimshowpigs(void)
86234353Sdim{
87239462Sdim	int i, j, y, k;
88234353Sdim	const char *uname, *pname;
89234353Sdim	char pidname[30];
90234353Sdim
91234353Sdim	if (pt == NULL)
92234353Sdim		return;
93243830Sdim
94243830Sdim	qsort(pt, nproc, sizeof (struct p_times), compar);
95249423Sdim	y = 1;
96249423Sdim	i = nproc;
97249423Sdim	if (i > wnd->_maxy-1)
98249423Sdim		i = wnd->_maxy-1;
99234353Sdim	for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
100243830Sdim		uname = user_from_uid(pt[k].pt_kp->ki_uid, 0);
101234353Sdim		pname = pt[k].pt_kp->ki_comm;
102234353Sdim		wmove(wnd, y, 0);
103234353Sdim		wclrtoeol(wnd);
104234353Sdim		mvwaddstr(wnd, y, 0, uname);
105234353Sdim		snprintf(pidname, sizeof(pidname), "%10.10s", pname);
106249423Sdim		mvwaddstr(wnd, y, 9, pidname);
107249423Sdim		wmove(wnd, y, 20);
108234353Sdim		for (j = pt[k].pt_pctcpu * 50 + 0.5; j > 0; j--)
109234353Sdim			waddch(wnd, 'X');
110234353Sdim	}
111234353Sdim	wmove(wnd, y, 0); wclrtobot(wnd);
112234353Sdim}
113234353Sdim
114234353Sdimint
115234353Sdiminitpigs(void)
116234353Sdim{
117234353Sdim	fixpt_t ccpu;
118249423Sdim	size_t len;
119249423Sdim	int err;
120249423Sdim
121249423Sdim	len = sizeof(ccpu);
122243830Sdim	err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0);
123234353Sdim	if (err || len != sizeof(ccpu)) {
124234353Sdim		perror("kern.ccpu");
125234353Sdim		return (0);
126234353Sdim	}
127234353Sdim
128243830Sdim	len = sizeof(fscale);
129234353Sdim	err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0);
130234353Sdim	if (err || len != sizeof(fscale)) {
131226633Sdim		perror("kern.fscale");
132234353Sdim		return (0);
133226633Sdim	}
134226633Sdim
135234353Sdim	lccpu = log((double) ccpu / fscale);
136226633Sdim
137226633Sdim	return(1);
138234353Sdim}
139234353Sdim
140226633Sdimvoid
141226633Sdimfetchpigs(void)
142234353Sdim{
143226633Sdim	int i;
144226633Sdim	float ftime;
145234353Sdim	float *pctp;
146234353Sdim	struct kinfo_proc *kpp;
147226633Sdim	static int lastnproc = 0;
148234353Sdim
149226633Sdim	if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
150226633Sdim		error("%s", kvm_geterr(kd));
151234353Sdim		if (pt)
152234353Sdim			free(pt);
153234353Sdim		return;
154226633Sdim	}
155234353Sdim	if (nproc > lastnproc) {
156205408Srdivacky		free(pt);
157205408Srdivacky		if ((pt =
158226633Sdim		    malloc(nproc * sizeof(struct p_times))) == NULL) {
159226633Sdim			error("Out of memory");
160226633Sdim			die(0);
161226633Sdim		}
162226633Sdim	}
163226633Sdim	lastnproc = nproc;
164226633Sdim	/*
165226633Sdim	 * calculate %cpu for each proc
166226633Sdim	 */
167226633Sdim	for (i = 0; i < nproc; i++) {
168205408Srdivacky		pt[i].pt_kp = &kpp[i];
169205408Srdivacky		pctp = &pt[i].pt_pctcpu;
170226633Sdim		ftime = kpp[i].ki_swtime;
171226633Sdim		if (ftime == 0 || (kpp[i].ki_flag & P_INMEM) == 0)
172226633Sdim			*pctp = 0;
173226633Sdim		else
174226633Sdim			*pctp = ((double) kpp[i].ki_pctcpu /
175226633Sdim					fscale) / (1.0 - exp(ftime * lccpu));
176226633Sdim	}
177226633Sdim}
178226633Sdim
179226633Sdimvoid
180226633Sdimlabelpigs(void)
181226633Sdim{
182226633Sdim	wmove(wnd, 0, 0);
183226633Sdim	wclrtoeol(wnd);
184226633Sdim	mvwaddstr(wnd, 0, 20,
185226633Sdim	    "/0%  /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
186226633Sdim}
187226633Sdim
188226633Sdimint
189226633Sdimcompar(const void *a, const void *b)
190226633Sdim{
191226633Sdim	return (((const struct p_times *) a)->pt_pctcpu >
192226633Sdim		((const struct p_times *) b)->pt_pctcpu)? -1: 1;
193226633Sdim}
194226633Sdim