xref: /original-bsd/usr.bin/systat/pigs.c (revision c6d5c0d7)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)pigs.c	5.8 (Berkeley) 02/04/91";
9 #endif not lint
10 
11 /*
12  * Pigs display from Bill Reeves at Lucasfilm
13  */
14 
15 #include "systat.h"
16 #include <sys/dir.h>
17 #include <sys/time.h>
18 #include <sys/proc.h>
19 #include <pwd.h>
20 #include <paths.h>
21 
22 WINDOW *
23 openpigs()
24 {
25 	return (subwin(stdscr, LINES-5-1, 0, 5, 0));
26 }
27 
28 closepigs(w)
29 	WINDOW *w;
30 {
31 	if (w == NULL)
32 		return;
33 	wclear(w);
34 	wrefresh(w);
35 	delwin(w);
36 }
37 
38 int	maxind;
39 int     factor;
40 float   total;
41 char    pidname[30];
42 long	stime[CPUSTATES];
43 double	idle;
44 
45 showpigs()
46 {
47 	register short auid;
48 	register int i, j, y;
49 	register float max;
50 	register struct p_times *ptptr;
51 	struct p_times temppt;
52 	register struct users *knptr;
53 	char *getpname(), *pnamp;
54 
55 	if (pt == NULL)
56 		return;
57 	/* Accumulate the percent of cpu per user. */
58 	ptptr = pt;
59 	numprocs = 0;
60 	total = 0.0;
61 	for (i = 0; i < nproc; i++) {
62 		/* discard inactive processes */
63 		if (ptptr->pt_uid == -1) {
64 			ptptr++;
65 			continue;
66 		}
67 		/* Accumulate the percentage. */
68 		total += ptptr->pt_pctcpu;
69 		numprocs++;
70 		ptptr++;
71 	}
72 
73 	pt[numprocs].pt_pctcpu = idle;
74 	total += idle;
75 	pt[numprocs].pt_uid = -1;
76 	pt[numprocs].pt_pid = -1;
77 	pt[numprocs].pt_pp = NULL;
78 
79 	if (total < 1.0)
80 		total = 1.0;
81 	factor = 50.0/total;
82 
83 	/* Find the top few by executing a "bubble pass" ten times. */
84 	y = numprocs + 1;
85 	if (y > wnd->_maxy-1)
86 		y = wnd->_maxy-1;
87 	for (i = 0; i < y; i++) {
88 		ptptr = &pt[i];
89 		max = -10000.0;
90 		maxind = i;
91 		for (j = i; j < numprocs + 1; j++) {
92 			if (ptptr->pt_pctcpu > max) {
93 				max = ptptr->pt_pctcpu;
94 				maxind = j;
95 			}
96 			ptptr++;
97 		}
98 		if (maxind != i) {
99 			temppt = pt[i];
100 			pt[i] = pt[maxind];
101 			pt[maxind] = temppt;
102 		}
103 	}
104 	y = 1;
105 	ptptr = pt;
106 	i = numprocs + 1;
107 	if (i > wnd->_maxy-1)
108 		i = wnd->_maxy-1;
109 	for (; i > 0 && ptptr->pt_pctcpu > 0.01; i--) {
110 		/* Find the user's name. */
111 		knptr = known;
112 		auid = ptptr->pt_uid;
113 		for (j = numknown - 1; j >= 0; j--) {
114 			if (knptr->k_uid == auid) {
115 				namp = knptr->k_name;
116 				break;
117 			}
118 			knptr++;
119 		}
120 		if (j < 0) {
121 			if (numknown < 30) {
122 				knptr = &known[numknown];
123 				namp = strncpy(knptr->k_name,
124 				    getpwuid(auid)->pw_name, 15);
125 				knptr->k_name[15] = '\0';
126 				knptr->k_uid = auid;
127 				numknown++;
128 			} else
129 				namp = getpwuid(auid)-> pw_name;
130 		}
131 		pnamp = getpname(ptptr->pt_pid, ptptr->pt_pp);
132 		wmove(wnd, y, 0);
133 		wclrtoeol(wnd);
134 		mvwaddstr(wnd, y, 0, namp);
135 		sprintf(pidname, "%10.10s", pnamp);
136 		mvwaddstr(wnd, y, 9, pidname);
137 		wmove(wnd, y++, 20);
138 		for (j = ptptr->pt_pctcpu*factor + 0.5; j > 0; j--)
139 			waddch(wnd, 'X');
140 		ptptr++;
141 	}
142 	wmove(wnd, y, 0); wclrtobot(wnd);
143 }
144 
145 static struct nlist nlst[] = {
146 #define X_PROC          0
147 	{ "_proc" },
148 #define X_NPROC         1
149 	{ "_nproc" },
150 #define X_USRPTMAP      2
151 	{ "_Usrptmap" },
152 #define X_USRPT         3
153 	{ "_usrpt" },
154 #define X_CPTIME	4
155 	{ "_cp_time" },
156 	{ "" }
157 };
158 
159 initpigs()
160 {
161 	if (nlst[X_PROC].n_type == 0) {
162 		nlist(_PATH_UNIX, nlst);
163 		if (nlst[X_PROC].n_type == 0) {
164 			error("namelist on %s failed", _PATH_UNIX);
165 			return(0);
166 		}
167 	}
168 	if (procp == NULL) {
169 		procp = getword(nlst[X_PROC].n_value);
170 		nproc = getword(nlst[X_NPROC].n_value);
171 	}
172 	if (kprocp == NULL)
173 		kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
174 	if (usrpt != NULL)
175 		return(1);
176 	usrpt = (struct pte *)nlst[X_USRPT].n_value;
177 	Usrptma = (struct pte *)nlst[X_USRPTMAP].n_value;
178 	if (pt == NULL)
179 		pt = (struct p_times *)calloc(nproc, sizeof (struct p_times));
180 	lseek(kmem, (long)nlst[X_CPTIME].n_value, L_SET);
181 	read(kmem, stime, sizeof stime);
182 	return(1);
183 }
184 
185 fetchpigs()
186 {
187 	register int i;
188 	register struct p_times *prt;
189 	register float time;
190 	register struct proc *pp;
191 	long ctime[CPUSTATES];
192 	double t;
193 
194 	if (nlst[X_PROC].n_type == 0)
195 		return;
196 	if (kprocp == NULL) {
197 		kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
198 		if (kprocp == NULL)
199 			return;
200 	}
201 	if (pt == NULL) {
202 		pt = (struct p_times *)calloc(nproc, sizeof (struct p_times));
203 		if (pt == NULL)
204 			return;
205 	}
206 	prt = pt;
207 	lseek(kmem, procp, L_SET);
208 	read(kmem, kprocp, sizeof (struct proc) * nproc);
209 	for (i = 0, pp = kprocp; i < nproc; i++, pp++) {
210 		time = pp->p_time;
211 		if (time == 0 || (pp->p_flag & SLOAD) == 0)
212 			continue;
213 		prt->pt_pid = pp->p_pid;
214 		prt->pt_pp = pp;
215 		prt->pt_pctcpu = ((double) pp->p_pctcpu / fscale) /
216 				(1.0 - exp(time * lccpu));
217 		prt->pt_uid = pp->p_uid;
218 		prt++;
219 	}
220 	for (; prt < &pt[nproc]; prt++)
221 		prt->pt_uid = -1;
222 	lseek(kmem, (long)nlst[X_CPTIME].n_value, L_SET);
223 	read(kmem, ctime, sizeof ctime);
224 	t = 0;
225 	for (i = 0; i < CPUSTATES; i++)
226 		t += ctime[i] - stime[i];
227 	if (t == 0.0)
228 		t = 1.0;
229 	idle = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
230 	for (i = 0; i < CPUSTATES; i++)
231 		stime[i] = ctime[i];
232 }
233 
234 labelpigs()
235 {
236 	wmove(wnd, 0, 0); wclrtoeol(wnd);
237 	mvwaddstr(wnd, 0, 20,
238 	    "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
239 }
240