xref: /csrg-svn/old/sdb/ps.c (revision 1346)
1*1346Sbill /*
2*1346Sbill  * ps; VAX 4BSD version
3*1346Sbill  */
4*1346Sbill 
5*1346Sbill #include <stdio.h>
6*1346Sbill #include <ctype.h>
7*1346Sbill #include <olda.out.h>
8*1346Sbill #include <pwd.h>
9*1346Sbill #include <sys/param.h>
10*1346Sbill #include <sys/tty.h>
11*1346Sbill #include <sys/dir.h>
12*1346Sbill #include <sys/user.h>
13*1346Sbill #include <sys/proc.h>
14*1346Sbill #include <sys/pte.h>
15*1346Sbill #include <sys/vm.h>
16*1346Sbill #include <sys/text.h>
17*1346Sbill #include <sys/stat.h>
18*1346Sbill 
19*1346Sbill struct nlist nl[] = {
20*1346Sbill 	{ "_proc" },
21*1346Sbill #define	X_PROC		0
22*1346Sbill 	{ "_Usrptma" },
23*1346Sbill #define	X_USRPTMA	1
24*1346Sbill 	{ "_usrpt" },
25*1346Sbill #define	X_USRPT		2
26*1346Sbill 	{ "_text" },
27*1346Sbill #define	X_TEXT		3
28*1346Sbill 	{ "_nswap" },
29*1346Sbill #define	X_NSWAP		4
30*1346Sbill 	{ 0 },
31*1346Sbill };
32*1346Sbill 
33*1346Sbill struct	savcom {
34*1346Sbill 	union {
35*1346Sbill 		struct	lsav *lp;
36*1346Sbill 		float	u_pctcpu;
37*1346Sbill 		struct	vsav *vp;
38*1346Sbill 		int	s_ssiz;
39*1346Sbill 	} sun;
40*1346Sbill 	struct	asav *ap;
41*1346Sbill } savcom[NPROC];
42*1346Sbill 
43*1346Sbill struct	asav {
44*1346Sbill 	char	*a_cmdp;
45*1346Sbill 	int	a_flag;
46*1346Sbill 	short	a_stat, a_uid, a_pid, a_nice;
47*1346Sbill 	size_t	a_size, a_rss;
48*1346Sbill 	char	a_tty[4];
49*1346Sbill 	dev_t	a_ttyd;
50*1346Sbill 	time_t	a_time;
51*1346Sbill };
52*1346Sbill 
53*1346Sbill char	*lhdr;
54*1346Sbill /*	    F S UID   PID  PPID CP PRI NICE ADDR  SZ  RSS WCHAN TTY TIME */
55*1346Sbill struct	lsav {
56*1346Sbill 	short	l_ppid;
57*1346Sbill 	char	l_cpu, l_pri;
58*1346Sbill 	int	l_addr;
59*1346Sbill 	caddr_t	l_wchan;
60*1346Sbill };
61*1346Sbill 
62*1346Sbill char	*uhdr;
63*1346Sbill /*	 USER       PID %%CPU NICE  SZ  RSS TTY TIME */
64*1346Sbill 
65*1346Sbill char	*shdr;
66*1346Sbill /*	 SSIZ   PID TTY TIME */
67*1346Sbill 
68*1346Sbill char	*vhdr;
69*1346Sbill /*	F     PID TT   TIME TIM SL  MINFLT  MAJFLT SIZE  RSS  SRS TSIZ TRS PF*/
70*1346Sbill struct	vsav {
71*1346Sbill 	short	v_slptime, v_pri;
72*1346Sbill 	u_int	v_minflt, v_majflt;
73*1346Sbill 	size_t	v_swrss, v_tsiz, v_txtrss, v_txtswrss;
74*1346Sbill 	short	v_xccount;
75*1346Sbill 	short	v_aveflt;
76*1346Sbill };
77*1346Sbill 
78*1346Sbill struct	proc mproc;
79*1346Sbill struct	text *text;
80*1346Sbill 
81*1346Sbill union {
82*1346Sbill 	struct	user user;
83*1346Sbill 	char	upages[UPAGES][NBPG];
84*1346Sbill } user;
85*1346Sbill #define u	user.user
86*1346Sbill 
87*1346Sbill #define clear(x) 	((int)x & 0x7fffffff)
88*1346Sbill 
89*1346Sbill int	chkpid;
90*1346Sbill int	aflg, cflg, gflg, kflg, lflg, sflg, uflg, vflg, xflg;
91*1346Sbill char	*tptr;
92*1346Sbill char	*gettty(), *getcmd(), *getname(), *savestr(), *alloc();
93*1346Sbill int	pscomp();
94*1346Sbill int	nswap;
95*1346Sbill struct	pte *Usrptma, *usrpt;
96*1346Sbill 
97*1346Sbill int	ndev;
98*1346Sbill struct devl {
99*1346Sbill 	char	dname[DIRSIZ];
100*1346Sbill 	dev_t	dev;
101*1346Sbill 	struct	devl *next;
102*1346Sbill 	struct	devl *cand;
103*1346Sbill } devl[256], *cand[16], *cons;
104*1346Sbill 
105*1346Sbill struct	savcom savcom[NPROC];
106*1346Sbill int	npr;
107*1346Sbill 
108*1346Sbill int	cmdstart;
109*1346Sbill int	twidth;
110*1346Sbill char	*kmemf, *memf, *swapf, *nlistf;
111*1346Sbill int	kmem, mem, swap;
112*1346Sbill 
113*1346Sbill int	pcbpf;
114*1346Sbill int	argaddr;
115*1346Sbill extern	char _sobuf[];
116*1346Sbill 
main(argc,argv)117*1346Sbill main(argc, argv)
118*1346Sbill 	char **argv;
119*1346Sbill {
120*1346Sbill 	register int i;
121*1346Sbill 	register char *ap;
122*1346Sbill 	int uid;
123*1346Sbill 	off_t procp;
124*1346Sbill 
125*1346Sbill 	setbuf(stdout, _sobuf);
126*1346Sbill 	argc--, argv++;
127*1346Sbill 	if (argc > 0) {
128*1346Sbill 		ap = argv[0];
129*1346Sbill 		while (*ap) switch (*ap++) {
130*1346Sbill 
131*1346Sbill 		case 'a':
132*1346Sbill 			aflg++;
133*1346Sbill 			break;
134*1346Sbill 		case 'c':
135*1346Sbill 			cflg = !cflg;
136*1346Sbill 			break;
137*1346Sbill 		case 'g':
138*1346Sbill 			gflg++;
139*1346Sbill 			break;
140*1346Sbill 		case 'k':
141*1346Sbill 			kflg++;
142*1346Sbill 			break;
143*1346Sbill 		case 'l':
144*1346Sbill 			lflg++;
145*1346Sbill 			break;
146*1346Sbill 		case 's':
147*1346Sbill 			sflg++;
148*1346Sbill 			break;
149*1346Sbill 		case 't':
150*1346Sbill 			if (*ap)
151*1346Sbill 				tptr = ap;
152*1346Sbill 			aflg++;
153*1346Sbill 			gflg++;
154*1346Sbill 			if (*tptr == '?')
155*1346Sbill 				xflg++;
156*1346Sbill 			while (*ap)
157*1346Sbill 				ap++;
158*1346Sbill 			break;
159*1346Sbill 		case 'u':
160*1346Sbill 			uflg++;
161*1346Sbill 			break;
162*1346Sbill 		case 'v':
163*1346Sbill 			cflg = 1;
164*1346Sbill 			vflg++;
165*1346Sbill 			break;
166*1346Sbill 		case 'w':
167*1346Sbill 			if (twidth == 80)
168*1346Sbill 				twidth = 132;
169*1346Sbill 			else
170*1346Sbill 				twidth = BUFSIZ;
171*1346Sbill 			break;
172*1346Sbill 		case 'x':
173*1346Sbill 			xflg++;
174*1346Sbill 			break;
175*1346Sbill 		default:
176*1346Sbill 			if (!isdigit(ap[-1]))
177*1346Sbill 				break;
178*1346Sbill 			chkpid = atoi(--ap);
179*1346Sbill 			*ap = 0;
180*1346Sbill 			aflg++;
181*1346Sbill 			xflg++;
182*1346Sbill 			break;
183*1346Sbill 		}
184*1346Sbill 	}
185*1346Sbill 	openfiles(argc, argv);
186*1346Sbill 	getkvars(argc, argv);
187*1346Sbill 	getdev();
188*1346Sbill 	uid = getuid();
189*1346Sbill 	printhdr();
190*1346Sbill 	procp = nl[X_PROC].n_value;
191*1346Sbill 	for (i=0; i<NPROC; i++) {
192*1346Sbill 		lseek(kmem, (char *)procp, 0);
193*1346Sbill 		if (read(kmem, (char *)&mproc, sizeof mproc) != sizeof mproc)
194*1346Sbill 			cantread("proc table", kmemf);
195*1346Sbill 		procp += sizeof (mproc);
196*1346Sbill 		if (mproc.p_stat == 0 || mproc.p_pgrp == 0 && xflg == 0)
197*1346Sbill 			continue;
198*1346Sbill 		if (tptr == 0 && gflg == 0 && xflg == 0 &&
199*1346Sbill 		    mproc.p_ppid == 1 && (mproc.p_flag&SDETACH) == 0)
200*1346Sbill 			continue;
201*1346Sbill 		if (uid != mproc.p_uid && aflg==0 ||
202*1346Sbill 		    chkpid != 0 && chkpid != mproc.p_pid)
203*1346Sbill 			continue;
204*1346Sbill 		if (vflg && gflg == 0 && xflg == 0) {
205*1346Sbill 			if (mproc.p_stat == SZOMB)
206*1346Sbill 				continue;
207*1346Sbill 			if (mproc.p_slptime > MAXSLP &&
208*1346Sbill 			    (mproc.p_stat == SSLEEP || mproc.p_stat == SSTOP))
209*1346Sbill 				continue;
210*1346Sbill 		}
211*1346Sbill 		save();
212*1346Sbill 	}
213*1346Sbill 	qsort(savcom, npr, sizeof(savcom[0]), pscomp);
214*1346Sbill 	for (i=0; i<npr; i++) {
215*1346Sbill 		register struct savcom *sp = &savcom[i];
216*1346Sbill 		if (lflg)
217*1346Sbill 			lpr(sp);
218*1346Sbill 		else if (vflg)
219*1346Sbill 			vpr(sp);
220*1346Sbill 		else if (uflg)
221*1346Sbill 			upr(sp);
222*1346Sbill 		else
223*1346Sbill 			spr(sp);
224*1346Sbill 		if (sp->ap->a_pid == 0)
225*1346Sbill 			printf(" swapper");
226*1346Sbill 		else if (sp->ap->a_pid == 2)
227*1346Sbill 			printf(" pagedaemon");
228*1346Sbill 		else
229*1346Sbill 			printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp);
230*1346Sbill 		printf("\n");
231*1346Sbill 	}
232*1346Sbill 	exit(npr == 0);
233*1346Sbill }
234*1346Sbill 
openfiles(argc,argv)235*1346Sbill openfiles(argc, argv)
236*1346Sbill 	char **argv;
237*1346Sbill {
238*1346Sbill 
239*1346Sbill 	kmemf = "/dev/kmem";
240*1346Sbill 	if (kflg)
241*1346Sbill 		kmemf = argc > 1 ? argv[1] : "/vmcore";
242*1346Sbill 	kmem = open(kmemf, 0);
243*1346Sbill 	if (kmem < 0) {
244*1346Sbill 		perror(kmemf);
245*1346Sbill 		exit(1);
246*1346Sbill 	}
247*1346Sbill 	if (kflg)  {
248*1346Sbill 		mem = kmem;
249*1346Sbill 		memf = kmemf;
250*1346Sbill 	} else {
251*1346Sbill 		memf = "/dev/mem";
252*1346Sbill 		mem = open(memf, 0);
253*1346Sbill 		if (mem < 0) {
254*1346Sbill 			perror(memf);
255*1346Sbill 			exit(1);
256*1346Sbill 		}
257*1346Sbill 	}
258*1346Sbill 	swapf = argc>2 ? argv[2]: "/dev/drum";
259*1346Sbill 	swap = open(swapf, 0);
260*1346Sbill 	if (swap < 0) {
261*1346Sbill 		perror(swapf);
262*1346Sbill 		exit(1);
263*1346Sbill 	}
264*1346Sbill }
265*1346Sbill 
getkvars(argc,argv)266*1346Sbill getkvars(argc, argv)
267*1346Sbill 	char **argv;
268*1346Sbill {
269*1346Sbill 	register struct nlist *nlp;
270*1346Sbill 
271*1346Sbill 	nlistf = argc > 3 ? argv[3] : "/vmunix";
272*1346Sbill 	nlist(nlistf, nl);
273*1346Sbill 	if (nl[0].n_type == 0) {
274*1346Sbill 		fprintf(stderr, "%s: No namelist\n", nlistf);
275*1346Sbill 		exit(1);
276*1346Sbill 	}
277*1346Sbill 	if (chdir("/dev") < 0) {
278*1346Sbill 		perror("/dev");
279*1346Sbill 		exit(1);
280*1346Sbill 	}
281*1346Sbill 	if (kflg)
282*1346Sbill 		for (nlp = nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++)
283*1346Sbill 			nlp->n_value = clear(nlp->n_value);
284*1346Sbill 	Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
285*1346Sbill 	usrpt = (struct pte *)nl[X_USRPT].n_value;
286*1346Sbill 	lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
287*1346Sbill 	if (read(kmem, &nswap, sizeof (nswap)) != sizeof (nswap)) {
288*1346Sbill /*###287 [lint] read arg. 2 used inconsistently ps.c(41) :: ps.c(287)%%%*/
289*1346Sbill 		cantread("nswap", kmemf);
290*1346Sbill /*###288 [lint] cantread arg. 1 used inconsistently ps.c(322) :: ps.c(288)%%%*/
291*1346Sbill /*###288 [lint] cantread arg. 2 used inconsistently ps.c(322) :: ps.c(288)%%%*/
292*1346Sbill 		exit(1);
293*1346Sbill 	}
294*1346Sbill 	if (vflg) {
295*1346Sbill 		text = (struct text *)alloc(NTEXT * sizeof (struct text));
296*1346Sbill 		if (text == 0) {
297*1346Sbill 			fprintf(stderr, "no room for text table\n");
298*1346Sbill 			exit(1);
299*1346Sbill 		}
300*1346Sbill 		lseek(kmem, (long)nl[X_TEXT].n_value, 0);
301*1346Sbill 		if (read(kmem, text, sizeof (text)) != sizeof (text)) {
302*1346Sbill /*###298 [lint] read arg. 2 used inconsistently ps.c(41) :: ps.c(298)%%%*/
303*1346Sbill 			cantread("text table", kmemf);
304*1346Sbill /*###299 [lint] cantread arg. 1 used inconsistently ps.c(322) :: ps.c(299)%%%*/
305*1346Sbill /*###299 [lint] cantread arg. 2 used inconsistently ps.c(322) :: ps.c(299)%%%*/
306*1346Sbill 			exit(1);
307*1346Sbill 		}
308*1346Sbill 	}
309*1346Sbill }
310*1346Sbill 
printhdr()311*1346Sbill printhdr()
312*1346Sbill {
313*1346Sbill 	char *hdr;
314*1346Sbill 
315*1346Sbill 	if (sflg+lflg+vflg+uflg > 1) {
316*1346Sbill 		fprintf(stderr, "ps: specify only one of s,l,v and u\n");
317*1346Sbill 		exit(1);
318*1346Sbill 	}
319*1346Sbill 	hdr = lflg ? lhdr : (vflg ? vhdr : (uflg ? uhdr : shdr));
320*1346Sbill 	if (lflg+vflg+uflg+sflg == 0)
321*1346Sbill 		hdr += strlen(" SSIZ");
322*1346Sbill 	cmdstart = strlen(hdr);
323*1346Sbill 	printf("%s COMMAND\n", hdr);
324*1346Sbill 	fflush(stdout);
325*1346Sbill }
326*1346Sbill 
cantread(what,fromwhat)327*1346Sbill cantread(what, fromwhat)
328*1346Sbill 	char *what, *fromwhat;
329*1346Sbill {
330*1346Sbill 
331*1346Sbill 	fprintf(stderr, "ps: error reading %s from %s", what, fromwhat);
332*1346Sbill }
333*1346Sbill 
getdev()334*1346Sbill getdev()
335*1346Sbill {
336*1346Sbill 	register FILE *df;
337*1346Sbill 	struct stat sbuf;
338*1346Sbill 	struct direct dbuf;
339*1346Sbill 
340*1346Sbill 	if ((df = fopen("/dev", "r")) == NULL) {
341*1346Sbill 		fprintf(stderr, "Can't open /dev\n");
342*1346Sbill 		exit(1);
343*1346Sbill 	}
344*1346Sbill 	ndev = 0;
345*1346Sbill 	while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) {
346*1346Sbill 		if (dbuf.d_ino == 0)
347*1346Sbill 			continue;
348*1346Sbill 		if (stat(dbuf.d_name, &sbuf) < 0)
349*1346Sbill 			continue;
350*1346Sbill 		if ((sbuf.st_mode&S_IFMT) != S_IFCHR)
351*1346Sbill 			continue;
352*1346Sbill 		strcpy(devl[ndev].dname, dbuf.d_name);
353*1346Sbill 		devl[ndev].dev = sbuf.st_rdev;
354*1346Sbill 		ndev++;
355*1346Sbill 	}
356*1346Sbill 	fclose(df);
357*1346Sbill }
358*1346Sbill 
save()359*1346Sbill save()
360*1346Sbill {
361*1346Sbill 	register struct savcom *sp;
362*1346Sbill 	register struct asav *ap;
363*1346Sbill 	register char *cp;
364*1346Sbill 	char *ttyp, *cmdp;
365*1346Sbill 
366*1346Sbill 	if (mproc.p_stat != SZOMB && getu() == 0)
367*1346Sbill 		return;
368*1346Sbill 	ttyp = gettty();
369*1346Sbill 	if (tptr && strcmpn(tptr, ttyp, 2))
370*1346Sbill 		return;
371*1346Sbill 	sp = &savcom[npr];
372*1346Sbill 	cmdp = getcmd();
373*1346Sbill 	if (cmdp == 0)
374*1346Sbill 		return;
375*1346Sbill 	sp->ap = ap = (struct asav *)alloc(sizeof (struct asav));
376*1346Sbill 	sp->ap->a_cmdp = cmdp;
377*1346Sbill #define e(a,b) ap->a = mproc.b
378*1346Sbill 	e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice);
379*1346Sbill 	e(a_uid, p_uid); e(a_pid, p_pid); e(a_rss, p_rssize);
380*1346Sbill #undef e
381*1346Sbill 	ap->a_size = mproc.p_dsize + mproc.p_ssize;
382*1346Sbill 	ap->a_tty[0] = ttyp[0];
383*1346Sbill 	ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' ';
384*1346Sbill 	ap->a_ttyd = u.u_ttyd;
385*1346Sbill 	ap->a_time = u.u_vm.vm_utime + u.u_vm.vm_stime;
386*1346Sbill 	if (lflg) {
387*1346Sbill 		register struct lsav *lp;
388*1346Sbill 
389*1346Sbill 		sp->sun.lp = lp = (struct lsav *)alloc(sizeof (struct lsav));
390*1346Sbill #define e(a,b) lp->a = mproc.b
391*1346Sbill 		e(l_ppid, p_ppid); e(l_cpu, p_cpu);
392*1346Sbill 		e(l_pri, p_pri); e(l_wchan, p_wchan);
393*1346Sbill #undef e
394*1346Sbill 		lp->l_addr = pcbpf;
395*1346Sbill 	} else if (vflg) {
396*1346Sbill 		register struct vsav *vp;
397*1346Sbill 		register struct text *xp;
398*1346Sbill 
399*1346Sbill 		sp->sun.vp = vp = (struct vsav *)alloc(sizeof (struct vsav));
400*1346Sbill #define e(a,b) vp->a = mproc.b
401*1346Sbill 		e(v_slptime, p_slptime); e(v_pri, p_pri);
402*1346Sbill 		e(v_swrss, p_swrss); e(v_aveflt, p_aveflt);
403*1346Sbill #undef e
404*1346Sbill 		vp->v_minflt = u.u_vm.vm_minflt;
405*1346Sbill 		vp->v_majflt = u.u_vm.vm_majflt;
406*1346Sbill 		if (mproc.p_textp) {
407*1346Sbill 			xp = &text[mproc.p_textp -
408*1346Sbill 			    (struct text *)nl[X_TEXT].n_value];
409*1346Sbill 			vp->v_tsiz = xp->x_size;
410*1346Sbill 			vp->v_txtrss = xp->x_rssize;
411*1346Sbill 			vp->v_txtswrss = xp->x_swrss;
412*1346Sbill 			vp->v_xccount = xp->x_ccount;
413*1346Sbill 		} else {
414*1346Sbill 			vp->v_tsiz = 0;
415*1346Sbill 			vp->v_txtrss = 0;
416*1346Sbill 			vp->v_xccount = 0;
417*1346Sbill 			vp->v_txtswrss = 0;
418*1346Sbill 		}
419*1346Sbill 	} else if (uflg)
420*1346Sbill 		sp->sun.u_pctcpu = 0.0;
421*1346Sbill 	else if (sflg) {
422*1346Sbill 		for (cp = (char *)u.u_stack;
423*1346Sbill 		    cp < (char *)&u + ctob(UPAGES); )
424*1346Sbill 			if (*cp++)
425*1346Sbill 				break;
426*1346Sbill 		sp->sun.s_ssiz = (int) ((char *)&u + ctob(UPAGES) - cp);
427*1346Sbill 	}
428*1346Sbill 	npr++;
429*1346Sbill }
430*1346Sbill 
getu()431*1346Sbill getu()
432*1346Sbill {
433*1346Sbill 	struct pte *pteaddr, apte, arguutl[UPAGES+CLSIZE];
434*1346Sbill 	register int i;
435*1346Sbill 	int ncl, size;
436*1346Sbill 
437*1346Sbill 	size = sflg ? ctob(UPAGES) : sizeof (struct user);
438*1346Sbill 	if ((mproc.p_flag & SLOAD) == 0) {
439*1346Sbill 		lseek(swap, ctob(mproc.p_swaddr), 0);
440*1346Sbill 		if (read(swap, (char *)&u, size) != size) {
441*1346Sbill 			fprintf(stderr, "ps: cant read u for pid %d from %s\n",
442*1346Sbill 			    mproc.p_pid, swapf);
443*1346Sbill 			return (0);
444*1346Sbill 		}
445*1346Sbill 		pcbpf = 0;
446*1346Sbill 		argaddr = 0;
447*1346Sbill 		return (1);
448*1346Sbill 	}
449*1346Sbill 	pteaddr = &Usrptma[btokmx(mproc.p_p0br) + mproc.p_szpt - 1];
450*1346Sbill 	lseek(kmem, kflg ? clear(pteaddr) : (int)pteaddr, 0);
451*1346Sbill 	if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
452*1346Sbill 		printf("ps: cant read indir pte to get u for pid %d from %s\n",
453*1346Sbill 		    mproc.p_pid, swapf);
454*1346Sbill 		return (0);
455*1346Sbill 	}
456*1346Sbill 	lseek(mem,
457*1346Sbill 	    ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0);
458*1346Sbill 	if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
459*1346Sbill 		printf("ps: cant read page table for u of pid %d from %s\n",
460*1346Sbill 		    mproc.p_pid, swapf);
461*1346Sbill 		return (0);
462*1346Sbill 	}
463*1346Sbill 	if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
464*1346Sbill 		argaddr = ctob(arguutl[0].pg_pfnum);
465*1346Sbill 	else
466*1346Sbill 		argaddr = 0;
467*1346Sbill 	pcbpf = arguutl[CLSIZE].pg_pfnum;
468*1346Sbill 	ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
469*1346Sbill 	while (--ncl >= 0) {
470*1346Sbill 		i = ncl * CLSIZE;
471*1346Sbill 		lseek(mem, ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
472*1346Sbill 		if (read(mem, user.upages[CLSIZE+i], CLSIZE*NBPG)
473*1346Sbill 		   != CLSIZE*NBPG) {
474*1346Sbill 			printf("ps: cant read page %d of u of pid %d from %s\n",
475*1346Sbill 			    arguutl[CLSIZE+i].pg_pfnum, mproc.p_pid, memf);
476*1346Sbill 			return(0);
477*1346Sbill 		}
478*1346Sbill 	}
479*1346Sbill 	return (1);
480*1346Sbill }
481*1346Sbill 
482*1346Sbill char *
getcmd()483*1346Sbill getcmd()
484*1346Sbill {
485*1346Sbill 	char cmdbuf[BUFSIZ];
486*1346Sbill 	union {
487*1346Sbill 		char	argc[CLSIZE*NBPG];
488*1346Sbill 		int	argi[CLSIZE*NBPG/sizeof (int)];
489*1346Sbill 	} argspac;
490*1346Sbill 	register char *cp;
491*1346Sbill 	register int *ip;
492*1346Sbill 	char c;
493*1346Sbill 	int nbad;
494*1346Sbill 	struct dblock db;
495*1346Sbill 
496*1346Sbill 	if (mproc.p_stat == SZOMB)
497*1346Sbill 		return ("");
498*1346Sbill 	if (cflg)
499*1346Sbill 		goto retucomm;
500*1346Sbill 	if ((mproc.p_flag & SLOAD) == 0 || argaddr == 0) {
501*1346Sbill 		vstodb(0, CLSIZE, &u.u_smap, &db, 1);
502*1346Sbill 		lseek(swap, ctob(db.db_base), 0);
503*1346Sbill 		if (read(swap, (char *)&argspac, sizeof(argspac))
504*1346Sbill 		    != sizeof(argspac))
505*1346Sbill 			goto bad;
506*1346Sbill 	} else {
507*1346Sbill 		lseek(mem, argaddr, 0);
508*1346Sbill 		if (read(mem, (char *)&argspac, sizeof (argspac))
509*1346Sbill 		    != sizeof (argspac))
510*1346Sbill 			goto bad;
511*1346Sbill 	}
512*1346Sbill 	ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)];
513*1346Sbill 	*--ip = 0;
514*1346Sbill 	while (*--ip)
515*1346Sbill 		if (ip == argspac.argi)
516*1346Sbill 			goto retucomm;
517*1346Sbill 	*(char *)ip = ' ';
518*1346Sbill 	ip++;
519*1346Sbill 	nbad = 0;
520*1346Sbill 	for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) {
521*1346Sbill 		c = *cp & 0177;
522*1346Sbill 		if (c == 0)
523*1346Sbill 			*cp = ' ';
524*1346Sbill 		else if (c < ' ' || c > 0176) {
525*1346Sbill 			if (++nbad >= 5) {
526*1346Sbill 				*cp++ = ' ';
527*1346Sbill 				break;
528*1346Sbill 			}
529*1346Sbill 			*cp = '?';
530*1346Sbill 		} else if (c == '=') {
531*1346Sbill 			while (*--cp != ' ')
532*1346Sbill 				if (cp <= (char *)ip)
533*1346Sbill 					break;
534*1346Sbill 			break;
535*1346Sbill 		}
536*1346Sbill 	}
537*1346Sbill 	*cp = 0;
538*1346Sbill 	while (*--cp == ' ')
539*1346Sbill 		*cp = 0;
540*1346Sbill 	cp = (char *)ip;
541*1346Sbill 	strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp);
542*1346Sbill 	if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
543*1346Sbill 		strcat(cp, " (");
544*1346Sbill 		strncat(cp, u.u_comm, sizeof(u.u_comm));
545*1346Sbill 		strcat(cp, ")");
546*1346Sbill 	}
547*1346Sbill 	if (xflg == 0 && gflg == 0 && tptr == 0 && cp[0] == '-')
548*1346Sbill 		return (0);
549*1346Sbill 	return (savestr(cmdbuf));
550*1346Sbill 
551*1346Sbill bad:
552*1346Sbill 	fprintf(stderr, "ps: error locating command name for pid %d\n",
553*1346Sbill 	    mproc.p_pid);
554*1346Sbill retucomm:
555*1346Sbill 	strcat(cp, " (");
556*1346Sbill 	strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm));
557*1346Sbill 	strcat(cp, ")");
558*1346Sbill 	return (savestr(cmdbuf));
559*1346Sbill }
560*1346Sbill 
561*1346Sbill char	*lhdr =
562*1346Sbill "    F S UID   PID  PPID CP PRI NICE ADDR  SZ  RSS WCHAN TTY TIME";
563*1346Sbill lpr(sp)
564*1346Sbill 	struct savcom *sp;
565*1346Sbill {
566*1346Sbill 	register struct asav *ap = sp->ap;
567*1346Sbill 	register struct lsav *lp = sp->sun.lp;
568*1346Sbill 
569*1346Sbill 	printf("%5x %c %4d%5u%6u%3d%4d%4d%6x%4d%5d",
570*1346Sbill 	    ap->a_flag, "0SWRIZT"[ap->a_stat], ap->a_uid,
571*1346Sbill 	    ap->a_pid, lp->l_ppid, lp->l_cpu&0377, lp->l_pri-PZERO,
572*1346Sbill 	    ap->a_nice-NZERO, lp->l_addr, ap->a_size, ap->a_rss);
573*1346Sbill 	printf(lp->l_wchan ? "%6x" : "      ", lp->l_wchan);
574*1346Sbill 	ptty(ap->a_tty);
575*1346Sbill 	ptime(ap);
576*1346Sbill }
577*1346Sbill 
ptty(tp)578*1346Sbill ptty(tp)
579*1346Sbill 	char *tp;
580*1346Sbill {
581*1346Sbill 
582*1346Sbill 	printf(" %-2.2s", tp);
583*1346Sbill }
584*1346Sbill 
585*1346Sbill ptime(ap)
586*1346Sbill 	struct asav *ap;
587*1346Sbill {
588*1346Sbill 
589*1346Sbill 	if (ap->a_stat == SZOMB)
590*1346Sbill 		printf("  <defunct>");
591*1346Sbill 	else
592*1346Sbill 		printf("%3ld:%02ld", ap->a_time / HZ, ap->a_time % HZ);
593*1346Sbill }
594*1346Sbill 
595*1346Sbill char	*uhdr =
596*1346Sbill "USER       PID %%CPU NICE  SZ  RSS TTY TIME";
597*1346Sbill upr(sp)
598*1346Sbill 	struct savcom *sp;
599*1346Sbill {
600*1346Sbill 	register struct asav *ap = sp->ap;
601*1346Sbill 
602*1346Sbill 	printf("%-8.8s%5u%5.1f%4d%4d%5d",
603*1346Sbill 	    getname(ap->a_uid), ap->a_pid, sp->sun.u_pctcpu, ap->a_nice,
604*1346Sbill 	    ap->a_size, ap->a_rss);
605*1346Sbill 	ptty(ap->a_tty);
606*1346Sbill 	ptime(ap);
607*1346Sbill }
608*1346Sbill 
609*1346Sbill char *vhdr =
610*1346Sbill "F     PID TT   TIME TIM SL  MINFLT  MAJFLT SIZE  RSS  SRS TSIZ TRS PF";
611*1346Sbill vpr(sp)
612*1346Sbill 	struct savcom *sp;
613*1346Sbill {
614*1346Sbill 	register struct vsav *vp = sp->sun.vp;
615*1346Sbill 	register struct asav *ap = sp->ap;
616*1346Sbill 	char stat, nice, anom;
617*1346Sbill 
618*1346Sbill 	switch (ap->a_stat) {
619*1346Sbill 
620*1346Sbill 	case SSLEEP:
621*1346Sbill 	case SSTOP:
622*1346Sbill 		if ((ap->a_flag & SLOAD) == 0)
623*1346Sbill 			stat = 'W';
624*1346Sbill 		else if (vp->v_pri >= PZERO)
625*1346Sbill 			stat = 'S';
626*1346Sbill 		else if (ap->a_flag & SPAGE)
627*1346Sbill 			stat = 'P';
628*1346Sbill 		else
629*1346Sbill 			stat = 'D';
630*1346Sbill 		break;
631*1346Sbill 
632*1346Sbill 	case SRUN:
633*1346Sbill 	case SIDL:
634*1346Sbill 		stat = ap->a_flag & SLOAD ? 'R' : 'W';
635*1346Sbill 		break;
636*1346Sbill 	}
637*1346Sbill 	nice = ap->a_nice > NZERO ? 'N' : ' ';
638*1346Sbill 	anom = ap->a_flag & (SANOM|SUANOM) ? 'A' : ' ';
639*1346Sbill 	printf("%c%c%c%5u", stat, nice, anom, ap->a_pid);
640*1346Sbill 	ptty(ap->a_tty);
641*1346Sbill 	ptime(ap);
642*1346Sbill 	printf("%3d%3d%8d%8d%5d%5d%5d%5d%4d%3d",
643*1346Sbill 	   ap->a_time, vp->v_slptime, vp->v_majflt, vp->v_minflt,
644*1346Sbill 	   ap->a_size, ap->a_rss, vp->v_swrss, vp->v_tsiz, vp->v_txtrss,
645*1346Sbill 	   vp->v_aveflt);
646*1346Sbill }
647*1346Sbill 
648*1346Sbill char	*shdr =
649*1346Sbill " SSIZ   PID TTY TIME";
650*1346Sbill spr(sp)
651*1346Sbill 	struct savcom *sp;
652*1346Sbill {
653*1346Sbill 	register struct asav *ap = sp->ap;
654*1346Sbill 
655*1346Sbill 	if (sflg)
656*1346Sbill 		printf("%5d", sp->sun.s_ssiz);
657*1346Sbill 	printf(" %5u", ap->a_pid);
658*1346Sbill 	ptty(ap->a_tty);
659*1346Sbill 	ptime(ap);
660*1346Sbill }
661*1346Sbill 
662*1346Sbill char *
gettty()663*1346Sbill gettty()
664*1346Sbill {
665*1346Sbill 	register i;
666*1346Sbill 	register char *p;
667*1346Sbill 
668*1346Sbill 	if (u.u_ttyp == 0)
669*1346Sbill 		return("?");
670*1346Sbill 	for (i=0; i<ndev; i++) {
671*1346Sbill 		if (devl[i].dev == u.u_ttyd) {
672*1346Sbill 			p = devl[i].dname;
673*1346Sbill 			if (p[0]=='t' && p[1]=='t' && p[2]=='y')
674*1346Sbill 				p += 3;
675*1346Sbill 			return(p);
676*1346Sbill 		}
677*1346Sbill 	}
678*1346Sbill 	return("?");
679*1346Sbill }
680*1346Sbill 
681*1346Sbill /*
682*1346Sbill  * Given a base/size pair in virtual swap area,
683*1346Sbill  * return a physical base/size pair which is the
684*1346Sbill  * (largest) initial, physically contiguous block.
685*1346Sbill  */
vstodb(vsbase,vssize,dmp,dbp,rev)686*1346Sbill vstodb(vsbase, vssize, dmp, dbp, rev)
687*1346Sbill 	register int vsbase;
688*1346Sbill 	int vssize;
689*1346Sbill 	struct dmap *dmp;
690*1346Sbill 	register struct dblock *dbp;
691*1346Sbill {
692*1346Sbill 	register int blk = DMMIN;
693*1346Sbill 	register swblk_t *ip = dmp->dm_map;
694*1346Sbill 
695*1346Sbill 	if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
696*1346Sbill 		panic("vstodb");
697*1346Sbill 	while (vsbase >= blk) {
698*1346Sbill 		vsbase -= blk;
699*1346Sbill 		if (blk < DMMAX)
700*1346Sbill 			blk *= 2;
701*1346Sbill 		ip++;
702*1346Sbill 	}
703*1346Sbill 	if (*ip <= 0 || *ip + blk > nswap)
704*1346Sbill 		panic("vstodb *ip");
705*1346Sbill 	dbp->db_size = min(vssize, blk - vsbase);
706*1346Sbill 	dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
707*1346Sbill }
708*1346Sbill 
709*1346Sbill /*ARGSUSED*/
panic(cp)710*1346Sbill panic(cp)
711*1346Sbill 	char *cp;
712*1346Sbill {
713*1346Sbill 
714*1346Sbill #ifdef DEBUG
715*1346Sbill 	printf("%s\n", cp);
716*1346Sbill #endif
717*1346Sbill }
718*1346Sbill 
min(a,b)719*1346Sbill min(a, b)
720*1346Sbill {
721*1346Sbill 
722*1346Sbill 	return (a < b ? a : b);
723*1346Sbill }
724*1346Sbill 
725*1346Sbill pscomp(s1, s2)
726*1346Sbill 	struct savcom *s1, *s2;
727*1346Sbill {
728*1346Sbill 	register int i;
729*1346Sbill 
730*1346Sbill 	if (vflg)
731*1346Sbill 		return (vsize(s2) - vsize(s1));
732*1346Sbill 	i = s1->ap->a_ttyd - s2->ap->a_ttyd;
733*1346Sbill 	if (i == 0)
734*1346Sbill 		i = s1->ap->a_pid - s2->ap->a_pid;
735*1346Sbill 	return (i);
736*1346Sbill }
737*1346Sbill 
738*1346Sbill vsize(sp)
739*1346Sbill 	struct savcom *sp;
740*1346Sbill {
741*1346Sbill 	register struct asav *ap = sp->ap;
742*1346Sbill 	register struct vsav *vp = sp->sun.vp;
743*1346Sbill 
744*1346Sbill 	if (ap->a_flag & SLOAD)
745*1346Sbill 		return (ap->a_rss +
746*1346Sbill 		    vp->v_txtrss / (vp->v_xccount ? vp->v_xccount : 1));
747*1346Sbill 	return (vp->v_swrss + (vp->v_xccount ? 0 : vp->v_txtswrss));
748*1346Sbill }
749*1346Sbill 
750*1346Sbill #define	NMAX	8
751*1346Sbill #define	NUID	2048
752*1346Sbill 
753*1346Sbill char	names[NUID][NMAX+1];
754*1346Sbill 
755*1346Sbill /*
756*1346Sbill  * Stolen from ls...
757*1346Sbill  */
758*1346Sbill char *
getname(uid)759*1346Sbill getname(uid)
760*1346Sbill {
761*1346Sbill 	register struct passwd *pw;
762*1346Sbill 	static init;
763*1346Sbill 	struct passwd *getpwent();
764*1346Sbill 
765*1346Sbill 	if (names[uid][0])
766*1346Sbill 		return (&names[uid][0]);
767*1346Sbill 	if (init == 2)
768*1346Sbill 		return (0);
769*1346Sbill 	if (init == 0)
770*1346Sbill 		setpwent(), init = 1;
771*1346Sbill 	while (pw = getpwent()) {
772*1346Sbill 		if (pw->pw_uid >= NUID)
773*1346Sbill 			continue;
774*1346Sbill 		if (names[pw->pw_uid][0])
775*1346Sbill 			continue;
776*1346Sbill 		strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
777*1346Sbill 		if (pw->pw_uid == uid)
778*1346Sbill 			return (&names[uid][0]);
779*1346Sbill 	}
780*1346Sbill 	init = 2;
781*1346Sbill 	endpwent();
782*1346Sbill 	return (0);
783*1346Sbill }
784*1346Sbill 
785*1346Sbill char	*freebase;
786*1346Sbill int	nleft;
787*1346Sbill 
788*1346Sbill char *
alloc(size)789*1346Sbill alloc(size)
790*1346Sbill 	int size;
791*1346Sbill {
792*1346Sbill 	register char *cp;
793*1346Sbill 	register int i;
794*1346Sbill 
795*1346Sbill 	if (size > nleft) {
796*1346Sbill 		freebase = (char *)sbrk(size > 2048 ? size : 2048);
797*1346Sbill 		if (freebase == 0) {
798*1346Sbill 			fprintf(stderr, "ps: ran out of memory\n");
799*1346Sbill 			exit(1);
800*1346Sbill 		}
801*1346Sbill 	}
802*1346Sbill 	cp = freebase;
803*1346Sbill 	for (i = size; --i >= 0; )
804*1346Sbill 		*cp++ = 0;
805*1346Sbill 	freebase = cp;
806*1346Sbill 	return (cp - size);
807*1346Sbill }
808*1346Sbill 
809*1346Sbill char *
savestr(cp)810*1346Sbill savestr(cp)
811*1346Sbill 	char *cp;
812*1346Sbill {
813*1346Sbill 	register int len;
814*1346Sbill 	register char *dp;
815*1346Sbill 
816*1346Sbill 	len = strlen(cp);
817*1346Sbill 	dp = (char *)alloc(len+1);
818*1346Sbill 	strcpy(dp, cp);
819*1346Sbill 	return (dp);
820*1346Sbill }
821