xref: /original-bsd/usr.bin/systat/pigs.c (revision 69a735b6)
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.6 (Berkeley) 05/11/89";
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 struct  passwd *getpwuid();
42 char    pidname[30];
43 long	stime[CPUSTATES];
44 double	idle;
45 
46 showpigs()
47 {
48 	register short auid;
49 	register int i, j, y;
50 	register float max;
51 	register struct p_times *ptptr;
52 	struct p_times temppt;
53 	register struct users *knptr;
54 	char *getpname(), *pnamp;
55 
56 	if (pt == NULL)
57 		return;
58 	/* Accumulate the percent of cpu per user. */
59 	ptptr = pt;
60 	numprocs = 0;
61 	total = 0.0;
62 	for (i = 0; i < nproc; i++) {
63 		/* discard inactive processes */
64 		if (ptptr->pt_uid == -1) {
65 			ptptr++;
66 			continue;
67 		}
68 		/* Accumulate the percentage. */
69 		total += ptptr->pt_pctcpu;
70 		numprocs++;
71 		ptptr++;
72 	}
73 
74 	pt[numprocs].pt_pctcpu = idle;
75 	total += idle;
76 	pt[numprocs].pt_uid = -1;
77 	pt[numprocs].pt_pid = -1;
78 	pt[numprocs].pt_pp = NULL;
79 
80 	if (total < 1.0)
81 		total = 1.0;
82 	factor = 50.0/total;
83 
84 	/* Find the top few by executing a "bubble pass" ten times. */
85 	y = numprocs + 1;
86 	if (y > wnd->_maxy-1)
87 		y = wnd->_maxy-1;
88 	for (i = 0; i < y; i++) {
89 		ptptr = &pt[i];
90 		max = -10000.0;
91 		maxind = i;
92 		for (j = i; j < numprocs + 1; j++) {
93 			if (ptptr->pt_pctcpu > max) {
94 				max = ptptr->pt_pctcpu;
95 				maxind = j;
96 			}
97 			ptptr++;
98 		}
99 		if (maxind != i) {
100 			temppt = pt[i];
101 			pt[i] = pt[maxind];
102 			pt[maxind] = temppt;
103 		}
104 	}
105 	y = 1;
106 	ptptr = pt;
107 	i = numprocs + 1;
108 	if (i > wnd->_maxy-1)
109 		i = wnd->_maxy-1;
110 	for (; i > 0 && ptptr->pt_pctcpu > 0.01; i--) {
111 		/* Find the user's name. */
112 		knptr = known;
113 		auid = ptptr->pt_uid;
114 		for (j = numknown - 1; j >= 0; j--) {
115 			if (knptr->k_uid == auid) {
116 				namp = knptr->k_name;
117 				break;
118 			}
119 			knptr++;
120 		}
121 		if (j < 0) {
122 			if (numknown < 30) {
123 				knptr = &known[numknown];
124 				namp = strncpy(knptr->k_name,
125 				    getpwuid(auid)->pw_name, 15);
126 				knptr->k_name[15] = '\0';
127 				knptr->k_uid = auid;
128 				numknown++;
129 			} else
130 				namp = getpwuid(auid)-> pw_name;
131 		}
132 		pnamp = getpname(ptptr->pt_pid, ptptr->pt_pp);
133 		wmove(wnd, y, 0);
134 		wclrtoeol(wnd);
135 		mvwaddstr(wnd, y, 0, namp);
136 		sprintf(pidname, "%10.10s", pnamp);
137 		mvwaddstr(wnd, y, 9, pidname);
138 		wmove(wnd, y++, 20);
139 		for (j = ptptr->pt_pctcpu*factor + 0.5; j > 0; j--)
140 			waddch(wnd, 'X');
141 		ptptr++;
142 	}
143 	wmove(wnd, y, 0); wclrtobot(wnd);
144 }
145 
146 static struct nlist nlst[] = {
147 #define X_PROC          0
148 	{ "_proc" },
149 #define X_NPROC         1
150 	{ "_nproc" },
151 #define X_USRPTMAP      2
152 	{ "_Usrptmap" },
153 #define X_USRPT         3
154 	{ "_usrpt" },
155 #define X_CPTIME	4
156 	{ "_cp_time" },
157 	{ "" }
158 };
159 
160 initpigs()
161 {
162 	if (nlst[X_PROC].n_type == 0) {
163 		nlist(_PATH_UNIX, nlst);
164 		if (nlst[X_PROC].n_type == 0) {
165 			error("namelist on %s failed", _PATH_UNIX);
166 			return(0);
167 		}
168 	}
169 	if (procp == NULL) {
170 		procp = getw(nlst[X_PROC].n_value);
171 		nproc = getw(nlst[X_NPROC].n_value);
172 	}
173 	if (kprocp == NULL)
174 		kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
175 	if (usrpt != NULL)
176 		return(1);
177 	usrpt = (struct pte *)nlst[X_USRPT].n_value;
178 	Usrptma = (struct pte *)nlst[X_USRPTMAP].n_value;
179 	if (pt == NULL)
180 		pt = (struct p_times *)calloc(nproc, sizeof (struct p_times));
181 	lseek(kmem, (long)nlst[X_CPTIME].n_value, L_SET);
182 	read(kmem, stime, sizeof stime);
183 	return(1);
184 }
185 
186 fetchpigs()
187 {
188 	register int i;
189 	register struct p_times *prt;
190 	register float time;
191 	register struct proc *pp;
192 	long ctime[CPUSTATES];
193 	double t;
194 
195 	if (nlst[X_PROC].n_type == 0)
196 		return;
197 	if (kprocp == NULL) {
198 		kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
199 		if (kprocp == NULL)
200 			return;
201 	}
202 	if (pt == NULL) {
203 		pt = (struct p_times *)calloc(nproc, sizeof (struct p_times));
204 		if (pt == NULL)
205 			return;
206 	}
207 	prt = pt;
208 	lseek(kmem, procp, L_SET);
209 	read(kmem, kprocp, sizeof (struct proc) * nproc);
210 	for (i = 0, pp = kprocp; i < nproc; i++, pp++) {
211 		time = pp->p_time;
212 		if (time == 0 || (pp->p_flag & SLOAD) == 0)
213 			continue;
214 		prt->pt_pid = pp->p_pid;
215 		prt->pt_pp = pp;
216 		prt->pt_pctcpu = pp->p_pctcpu / (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