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