/*
 *	stat - print system process status
 *
 *	Author:	John Buck
 *	Polytechnic Inst. Summer 1981
 *
 *	cc -i stat.c -o stat -O
 *	chmod 02711 stat
 *	chgrp 0 stat
 *	mv stat wherever
 *
 *	Usage:
 *	stat [-p] [-o [dev1 dev2 ...]] [-i] [-f] [-r] [-R#] [-tx] [-s]
 *		[-e [-I] [-n] [-h] [-d] [-b] [-c] corefile swapfile
 *
 *	-p      Print pipes
 *	-f      Full: Print proc status, Pipes, Open files on all devs
 *	-r      Print Root procs, I.E. UID=0
 *	-R#	Repeat status report every # seconds.
 *	-h	Print Informatory header (Time date etc...)
 *	-s      Print status only (default)
 *	-b	Print Entire command, as stat understands it (5120 char max)
 *	-e	Print signal disposition for procs.
 *		T = being privately trapped
 *		I = being ignored
 *		- = Normal handling.
 *	-n      When printing open files on /, do not print tty's
 *	-d      Print disk structure
 *	-i      Print only "In-core" processes, (Flag & 1) == 1
 *	-w      Print Working Directories
 *	-l	Print long process listing
 *	-c      Take next arg as core file, and one after that as swap
 *		Default to /sys/sys/core and /dev/rm8 respectively
 *	-tx     Print info only for procs on ttyx.
 *	-I	Turn on toggle that will cause any of the open file routines
 *		NOT to look-up the filename for an inode.  It will just print
 *		the info found in the inode structure on the device.
 *	-o      Print open files on all devices.  If arguments follow (without
 *		'-' characters first), files open on these devices will NOT
 *		be printed. So, to get all open files, except on rm0,
 *		stat -o rm0
 *
 *	Furthermore, an optional first argument of a login name or uid specifies
 *	info for this person only will be printed.
 *
 *	stat john      or     stat 47
 *	will print info for users 'john' (UID=47)  only.
 *
 */



#include "sys/types.h"
#include "sys/param.h"
#include "sys/filsys.h"
#include "sys/inode.h"
#include "sys/ino.h"
#include "sys/dir.h"
#include "sys/file.h"
#include "sys/signal.h"
#include "sys/proc.h"
#include "sys/user.h"
#include "sys/text.h"
#include "sys/tty.h"
#include "sys/utsname.h"
#include "sys/sysinfo.h"
#include "sys/var.h"
#include "mnttab.h"

#define MAXDV   20
#define NINDE  INOPB*16
#define NOFTAB  300
#define NI      200
#define NDIRS   1699

struct  inode in;
struct	dinode	finode[NINDE];
struct  file fil;
struct  proc pdb;
struct  user us;
struct  text txt;
struct  sysinfo sysinfo;
struct 	var	v;
struct	utsname	utsname;
struct  filsys  sblock;
struct mnttab mnt;
struct	stb  {
	int devc;
	int inumber;
	int flags;
	short nlinks;
	short uuid;
	short ggid;
	short rdev;
	long size1;
	long	actime;
	long	modtime;
	long	crtime;
} st;

struct  htab {
	int     hino;
	int     hpino;
	char    hname[14];
} htab[NDIRS];

struct	{
	int	sint;
};

struct  {
	char nm[8];
	int type;
	unsigned value;
}nl[8];

struct  dtab {
	int dv;
	int in;
	int pid;
	short uid;
	short gid;
	char fd;
	char flg;
	long offset;
	char who[9];
} tab[NOFTAB];
struct  dtab *ts;


char	*SWPDV =    "/dev/swap";
char	*UNIX =		"/unix";
int	swpflg = 0;
int	coreflg = 0;
long	systime;
char    name[16];
unsigned     extflag = 0;
char    dvlst[MAXDV][8];
int     ndv = 0;
short	ntty = 0;
char	**wttyp;
char	*wtty[64];
int     aflg    = 1;
int     ilist[NI] { -1};
long	nad[NADDR];
int     fi;
int     nhent   10;
int     pass1(), pass2(), pass3();
int     (*pass[])()     { pass1, pass2, pass3 };
int     ino;
char    fbf[512] , *ff , *pf;
int     nfiles;
char	*ttyc;
char    filesys[32];
long    lhold;
int     nrm0 = 0;
int     adv , nof = 0;
char    *core   "/dev/mem";
char    *tc() , *mknm(), *oper();
long	swplo;		/* Used for analyzing swap space dumps. */
char	udata[16];

int     oldfout;
int	mm;
/*
int     fout;
*/
long	bootime;
long	uptime;
long	maddr;


main(argc, argv)
char **argv;
{
	long	b, l;
	int mem , tmp , i , swp;
	short ptb;
	register unsigned flag;
	register char *s;
	register int j;
	char *t;
	int hdflg;
	int pid = 0;
	int reptim = 0;
	short myuid;

	myuid = 0;

	swpflg = 0;
	ptb = getgid() ;
	if(ptb != 0 && ptb != 2){
		ptb = getuid() ;
		if(ptb != 0 && ptb != 47 && ptb != 5){
			myuid = ptb;
		}
	}

	s = 0;
	while(--argc) {
		argv++;
		if(**argv != '-') {
			s = *argv;
			while(*s >= '0' && *s <= '9')
				pid = pid * 10 + (*s++) - '0';
			if(pid)s = 0;
			else    {
				s = name;
				cps(s, *argv);
			}

			if(pid < 0) {
				printf("Invalid UID: %d\n",pid);
				exit(1);
			}
			flag |= 1;
		} else {
			switch(*++(*argv)) {

		case	'R':
			t = (*argv) + 1;
			reptim = 0;
			flag |= 4097;
			while(*t >= '0' && *t <= '9')
				reptim = reptim * 10 + (*t++) - '0';
			if(reptim < 0 || reptim > 600)
				goto nosir;
			break;

		case    'p':
			flag |= 2;
			nrm0 = 1;
			break;

		case	'q':
			if(myuid)
				goto nosir;
			nice(-120);
			break;

		case	'u':
			if(myuid)
				goto nosir;
			if ( argc > 1 ){
				UNIX = *++argv;
				argc--;
			}
			break;

		case    'c':
			if(myuid)
				goto nosir;
			coreflg++;
			if(argc > 1 && **(argv+1) != '-'){
				argc--;
				core = *++argv;
				if(argc > 1 && **(argv+1) != '-'){
					argc--;
					SWPDV = *++argv;
					swpflg = 1;
				}
			}
			else	core = "/usr/src/uts/core";
			break;

		case	'I':
			flag ^= 8192;
			break;

		case    'o':
			flag |= 4;
			nrm0 = 1;
			while(--argc && *(*++argv) != '-')
				if(ndv < MAXDV)
					cps(dvlst[ndv++], *argv);
			argv--;
			argc++;
			break;

		case    'f':
			flag |= 1703;
			nrm0 = 1;
			break;

		case    'r':
			flag |= 9;
			break;

		case    't':
			t = *argv + 1;
			wtty[ntty++] = t;
			while(*t){
				if(*t == ','){
					*t = 0;
					wtty[ntty++] = t+1;
				}
				t++;
			}

		case    's':
			flag |= 1;
			break;
		case	'S':
			flag |= 1025;
			break;
		case	'b':
			flag |= 2049;
			break;


		case    'i':
			flag |= 65;
			break;

		case    'n':
			flag |= 16;
			break;

		case    'w':
			flag |= 128;
			nrm0 = 1;
			break;

		case	'l':
			flag |= 257;
			break;

		case    'd':
			flag |= 32;
			break;

		case	'h':
			flag |= 513;
			break;

		case	'e':
			flag |= 18433;
			break;

		case	'T':
			flag |= (unsigned)(32769);
			break;

		default:
nosir:
			printf("\nIllegal Option or Argument\n\n");
			exit(1);
			break;
			}
		}
	}

	wtty[ntty] = 0;
	if(myuid){
		if((pid && pid != myuid) ||
			(s && strcmp(s, logname())) ||
			(flag & (2+4+8+16+128+1024+8192)) ||
			nrm0)
			goto nosir;
		pid = myuid;
	}
	if(flag & 4096){
		flag &= 8025;
		nrm0 = 0;
	}
	if((flag & 175) == 0)
		flag = 1;
	extflag = flag;
	if(flag == 32)
		goto skipthis;
	cps(&nl[0], "_proc");
	cps(&nl[1], "_time");
	cps(&nl[2], "_swplo");
	cps(&nl[3], "_sysinfo");
	cps(&nl[4], "_v");
	cps(&nl[5], "_utsname");
	nlist(UNIX, nl);
	if(nl[0].type < 0){
		write(2,"No namelist\n",12);
		exit(1);
	}

	if((mem = open(core,0)) == -1){
		write(2,"Permission denied.\n",19);
		exit(2);
	}

	hdflg = 0;
	if((mm = open(core,0)) == -1 ||
	   (swp = open(SWPDV,0)) == -1) {
		printf("No swap device.\n");
		exit(1);
	}
	lseek(mem, (long)(nl[2].value), 0);
	read(mem, &swplo, 4);
	lseek(mem, (long)(nl[4].value), 0);
	read(mem, &v, sizeof (struct var));
/*
	oldfout = fout;
	fout = dup(1);
*/
repeat:
	if(flag & 512) {
		lseek(mem, (long)(nl[1].value), 0);
		read(mem, &systime, 4);
		prheadr();
	}
	lseek(mem, (long)(nl[0].value), 0);
	for(ptb = 1; ptb <= v.v_proc; ptb++) {
		read(mem, &pdb, sizeof (struct proc));
		if((flag & 64) && (pdb.p_flag & 1) == 0)continue;
		if(pdb.p_stat == 0 || pdb.p_stat == 4 || pdb.p_stat == 5)continue;
		if((nrm0 == 0 && (flag & 8) == 0 && pdb.p_uid == 0) ||
		   (pid && pid != pdb.p_uid))continue;
		b = l = 0;
		if(pdb.p_flag & 1) {
			i = mm;
			b = l = (long)(pdb.p_addr) << 6;
		}
		else    {
			i = swp;
			b = (pdb.p_addr + swplo);
			if(swpflg)
				b -= swplo;
			l = b << 9;
		}

		lseek(i,l,0);
		if(read(i,&us,sizeof us) != sizeof us)continue;
		maddr = b;
		strncpy(udata, us.u_udata, 8);
		udata[8] = 0;
		if(s && eql(udata,s) == 0)continue;

		ttyc = us.u_udata + 40;
		if(*ttyc == 't' && ttyc[1] == 't' && ttyc[2] == 'y')
			ttyc += 3;
		ttyc[8] = 0;

		for(wttyp = wtty; *wttyp; wttyp++)
			if(eql(*wttyp, ttyc))break;
		if(ntty && *wttyp == 0)
			continue;
		if(flag & 1 && hdflg == 0){
			if(flag & 256)
				printf("\nLog-nm");
			else	printf("\nLog-name");
			printf(" TT   Uid Gid");
			if(flag & 256)
				printf(" RUid RGi");
			printf(" SFl Parnt  Proc");
			if(flag & 256)
				printf(" PrGrp");
			printf(" Sh/Sz Nic Pr Op Cpu");
			if(flag & 256)
				printf(" SwpAddr  TxtAdr WaChan Sig Msk Clk");
			if(flag & (unsigned)(32768))
				printf("    Usr-Time    Sys-Time");
			else printf("    Run-Time");
			if(flag & 256)
				if(flag & (unsigned)(32768))
					printf(" Chd-U-Time Chd-S-Time");
				else	printf(" Child-Time");
			printf(" Command\n");
			hdflg = 1;

		}
		if((flag & 1) && (pdb.p_uid || (flag & 8))) {
			printf((flag & 256) ? "%-6.6s" : "%-8.8s", udata);
			printf(" %2.2s%6d%4d",ttyc,pdb.p_uid, us.u_gid);
			if(flag & 256)
				printf("%5d%4d",us.u_ruid,  us.u_rgid);
			printf(" %c%2o%6d%6d"," SWRIZTEK"[pdb.p_stat],
					pdb.p_flag & 077,pdb.p_ppid,pdb.p_pid);
			if(flag & 256)
				printf("%6d",pdb.p_pgrp);
			if(pdb.p_textp){
				lseek(mm, (long)(pdb.p_textp), 0);
				read(mm,&txt,sizeof txt);
				printf(" %2d/",(txt.x_size + 15) >> 4);
			}
			else    printf("    ");
			printf("%2d%4d%3d %2.2s%4d",(pdb.p_size+15) >> 4,
					pdb.p_nice,pdb.p_pri, oper(&pdb),
					(int)(pdb.p_cpu) & 0377);
			if(flag & 256){
				printf("%8O%c", maddr,
					(pdb.p_flag & 1) ? ' ' : 'B');
				if(pdb.p_textp)
					printf("%7o", pdb.p_textp);
				else	printf(" ------");
				if(pdb.p_wchan)
					printf("%7o",pdb.p_wchan);
				else	printf(" ------");
				printf("%4D%4o%4d",pdb.p_sig, us.u_cmask, pdb.p_clktim);
			}
			if(flag & (unsigned)(32768)){
				printf("%12.12s", tc(us.u_utime, 0));
				printf("%12.12s", tc(us.u_stime, 0));
			}
			else
				printf("%12.12s",tc(us.u_utime+us.u_stime,0));
			if(flag & 256)
				if(flag & (unsigned)(32768)){
					printf("%11.11s", tc(us.u_cutime, 0));
					printf("%11.11s", tc(us.u_cstime, 0));
				}
				else	printf("%11.11s", tc(us.u_cutime + us.u_cstime, 0));
			if(pdb.p_pid == 0) {
				printf(" Swapper");
				goto nocmd;
			}
			if(pdb.p_pid == 1) {
				printf(" init");
				goto nocmd;
			}
			l += (long)(pdb.p_size - 8) << 6;
			lseek(i, l, 0);
			prcom(i);
nocmd:
		printf("\n");
			if(flag & 1024) {
				printf("Signals: ");
				for(j = 0; j < NSIG; j++)
					printf("%c", (us.u_signal[j] == 0) ? '-' :
						(us.u_signal[j] == 1) ? 'I' : 'T');
				printf("\n\n");
			}
			flush();

		}
		if(nrm0 == 0 || nof >= NOFTAB-16)continue;
		if((flag & 6) == 0)goto getwd;
		for(j = 0; j < NOFILE;j++){
			if(us.u_ofile[j] == 0)continue;
			lseek(mm, (long)(us.u_ofile[j]), 0);
			if(read(mm,&fil,sizeof fil) != sizeof fil)continue;
			lseek(mm, (long)(fil.f_inode), 0);
			if(read(mm,&in,sizeof (struct inode)) != sizeof (struct inode))continue;
			if((eql("(login:)",udata) || flag & 16) &&
				in.i_blks.i_p.i_r == us.u_ttyd)continue;
pwd:
			ts = &tab[nof++];
			ts->offset = fil.f_offset;
			ts->dv = in.i_dev;
			ts->in = in.i_number;
			ts->pid = pdb.p_pid;
			ts->uid = pdb.p_uid;
			ts->gid = us.u_gid;
			ts->fd = j;
			ts->flg = fil.f_flag;
			if((in.i_mode & IFMT) == IFIFO)
				ts->flg |= 040;
			cps(ts->who,udata);
			if(j == -1)goto gotpwd;
		}
getwd:
		if((flag & 128) == 0)continue;
		if((flag & 8) == 0 && eql("(login:)",udata))continue;
		lseek(mm, (long)(us.u_cdir), 0);
		read(mm,&in, sizeof (struct inode));
		j = -1;
		fil.f_flag = 0200;
		goto pwd;
gotpwd:
		/* We have just gotten the working directory */;
	}
	flush();
	if(flag & 4096){
		if(reptim)sleep(reptim);
		hdflg = 0;
		goto repeat;
	}

/*
	close(fout);
	fout = oldfout;
*/
	if(flag & 2){
		printf("\n\nPipes: ");
		for(i = j = 0; j < nof; j++) {
			ts = &tab[j];
			if((ts->flg & 04) == 0)continue;
			i++;
			printf("\n Proc  Who     Uid Gid  FD  How\n");
			for(ptb = 0; ptb < nof; ptb++) {
				if(tab[ptb].flg & 040 && ts->dv == tab[ptb].dv &&
				   ts->in == tab[ptb].in) {
					printf("%5d %-8.8s %3d %3d  %2d  ",
						tab[ptb].pid,tab[ptb].who,
						tab[ptb].uid,tab[ptb].gid,
						tab[ptb].fd);
					if(tab[ptb].flg & FREAD)
						printf("Read");
					if(tab[ptb].flg & FWRITE){
						if(tab[ptb].flg & FREAD)
							printf(", ");
						printf("Write");
					}
					if(tab[ptb].flg & FNDELAY){
						if(tab[ptb].flg & (FREAD|FWRITE))
							printf(", ");
						printf(" No delay");
					}
					printf("\n");
					tab[ptb].flg = 0100;
				}
			}
		}
		if(i == 0)printf("None\n");
		flush();
	}


	if(flag & 132)fils();
skipthis:
	if(flag & 32) {
		printf("\nDisk Structure:\n");
		disk();
		flush();
	}


	close(mm);
	close(swp);
	close(mem);
	printf("\n");
	flush();
}

cps(s,t)
register char *s , *t;
{
	while(*s++ = *t++);
}





fils(){
	register i , *j, *k;
	int mf;


	chdir("/dev");
	if((mf = open("/etc/mnttab",0)) == -1)return;
	while(read(mf,&mnt,sizeof mnt) == sizeof mnt){
		if(mnt.mt_dev[0] == 0 || mnt.mt_filsys[0] == 0)
			continue;
		for(i = 0; i < ndv; i++)
			if(eql(dvlst[i],mnt.mt_dev))break;
		if(i < ndv)continue;
		mnt.mt_filsys[9] = 0;
		cps(filesys,mnt.mt_filsys);
		if(stat(filesys,&st))continue;
		adv = st.devc;
		j = ilist;
		mnt.mt_dev[9] = 0;
		for(i = 0; i < nof; i++)
			if(tab[i].dv == adv && (tab[i].flg & 010) == 0){
				*j = tab[i].in;
				for(k = ilist; k < j; k++)
					if(*k == *j)break;
				if(k >= j)
					if(j == &ilist[NI-1])
						printf("Too many file descriptors on %s\n",
							filesys);
					else	j++;
			}

		if(j != ilist) {
			*j = -1;
			printf("\n\n");
			check(mnt.mt_dev);
		}
	}
	printf("\n\n");
	close(mf);
}

char    *tc(tic, fff)
int fff;
long tic;
{
	register char *s , *t , pchar;
	int fra , sec , mint , hr;
	static char tbuf[16];

	if(fff)tic *= 60L;
	fra = (((int)(tic % 60L)) * 10)/60;
	tic =/ 60L;
	sec = (int)(tic % 60L);
	tic =/ 60L;
	mint = (int)(tic % 60L);
	hr = (int)(tic / 60L);
	if(hr > 999){
		if(fff)return("???:??:??");
		else	return("???:??:??.?");
	}
	pchar = ' ';
	t = tbuf;

	if(hr) {
		s = t + 3;
		*s = ':';
		fill(s++,t,pchar,hr);
		pchar = '0';
		t = s;
	}

	if(mint || pchar == '0') {
		s = t + 2;
		*s = ':';
		fill(s++,t,pchar,mint);
		pchar = '0';
		t = s;
	}

	s = t + 2;
	fill(s,t,pchar,sec);
	if(fff == 0){
		*s++ = '.';
		*s++ = fra + '0';
	}
	*s = 0;
	return(tbuf);
}


fill(s,t,pchar,v)
register char *s , *t;
char pchar;
int v;
{
	register i;
	i = v;
	while(i) {
		*--s = i % 10 + '0';
		i =/ 10;
	}
	if(v == 0)*--s = '0';
	while(s > t)*--s = pchar;
}


check(file)
char *file;
{
	register i, j, pno;
	char *mkrm();

	fi = open(mkrm(file), 0);
	if (fi < 0) {
		printf("\nDevice \"%s\" not available\n\n",file);
		flush();
		return;
	}
	printf("\n\nOpen files and who is accessing them on \"%s\", (%s):\n",
		file,filesys);
	sync();
	bread(1L, &sblock, sizeof (sblock));
	nfiles = (sblock.s_isize-2)*INOPB;
	nhent = 10;
	flush();
	if(extflag & 8192)
		goto finish;	/* Do not want names, just inode */
	for (i=0; i<NDIRS; i++)
		htab[i].hino = 0;
	for (pno=0; pno<3; pno++) {
		ino = 0;
		for (i=0; ino<nfiles; i =+ NINDE/INOPB) {
			bread((long)(i+2), finode, sizeof finode);
			for (j=0; j<NINDE && ino<nfiles; j++) {
				ino++;
				(*pass[pno])(&finode[j]);
				if(ilist[0] == -1) {
					close(fi);
					return(0);
				}

			}
		}
	}
finish:
	while(ilist[0] != -1)
		op("/????????",ilist[0]);
	close(fi);
}

pass1(ip)
struct dinode *ip;
{
	if((ip->di_mode & IFMT) == IFDIR)
		lookup(ino, 1);
	return;
}

pass2(ip)
struct dinode *ip;
{
	register doff;
	register struct htab *hp;
	register struct direct *dp;
	int i;

	if ((ip->di_mode & IFMT) != IFDIR)
		return;
	doff = 0;
	l3tol(nad, ip->di_addr, NADDR);
	while (dp = dread(ip, doff)) {
		doff =+ 16;
		if (dp->d_ino==0)
			continue;
		if ((hp = lookup(dp->d_ino, 0)) == 0)
			continue;
		if (dotname(dp))
			continue;
		hp->hpino = ino;
		for (i=0; i<14; i++)
			hp->hname[i] = dp->d_name[i];
	}
}

pass3(ip)
struct dinode *ip;
{
	register doff;
	register struct direct *dp;
	register int *ilp;

	if ((ip->di_mode & IFMT) != IFDIR)
		return;
	doff = 0;
	l3tol(nad, ip->di_addr, NADDR);
	while (dp = dread(ip, doff)) {
		doff =+ 16;
		if (dp->d_ino==0)
			continue;
		for (ilp=ilist; *ilp >= 0; ilp++)
			if (*ilp == dp->d_ino)
				break;
		if(*ilp == -1)
			continue;
		ff = fbf;
		pname(ino,0);
		pf = dp->d_name;
		*ff++ = '/';
		while(pf < dp->d_name+14 && (*ff++ = *pf++));
		*ff = 0;
		if(op(fbf,dp->d_ino) == -1)return(1);
	}
	return(0);
}

dotname(adp)
{
	register struct direct *dp;

	dp = adp;
	if (dp->d_name[0]=='.')
		if (dp->d_name[1]==0 || dp->d_name[1]=='.' && dp->d_name[2]==0)
			return(1);
	return(0);
}

pname(i, lev)
{
	register struct htab *hp;

	if (i==2)
		return;
	if ((hp = lookup(i, 0)) == 0) {
		*ff++ = '?';
		*ff++ = '?';
		*ff++ = '?';
		return;
	}
	if (lev > 10) {
		*ff++ = '.';
		*ff++ = '.';
		*ff++ = '.';
		return;
	}
	pname(hp->hpino, ++lev);
	*ff++ = '/';
	pf = hp->hname;
	while(pf < hp->hname+14 && (*ff++ = *pf++));
	if(*(ff-1) == 0)ff--;
}

lookup(i, ef)
{
	register struct htab *hp;

	for (hp = &htab[i%NDIRS]; hp->hino;) {
		if (hp->hino==i)
			return(hp);
		if (++hp >= &htab[NDIRS])
			hp = htab;
	}
	if (ef==0)
		return(0);
	if (++nhent >= NDIRS) {
		printf("Out of core-- increase NDIRS\n");
		exit(1);
	}
	hp->hino = i;
	return(hp);
}

dread(aip, aoff)
{
	register b, off;
	register struct dinode *ip;
	static long ibuf[128];
	static char buf[512];

	off = aoff;
	ip = aip;
	if ((off&0777)==0) {
		if (off==0177000) {
			printf("Monstrous directory %l\n", ino);
			return(0);
		}
		if((b = off >> 9) < 10){
			if(nad[b] == 0)
				return(0);
			bread(nad[b], buf, 512);
		} else {
			if(off == 5120){
				if(nad[10] == 0)
					return(0);
				bread(nad[10], ibuf, 512);
			}
			b -= 10;
			if((b = ibuf[b]) == 0)
				return(0);
			bread((long)(b), buf, 512);
		}
	}
	return(&buf[off&0777]);
}

bread(bno, buf, cnt)
long	bno;
{

	lseek(fi, bno << 9, 0);
	if (read(fi, buf, cnt) != cnt) {
		printf("read error %D\n", bno);
		abort();
		exit();
	}
}



op(s,i)
char *s;
int i;
{
	register n , *hflg;
	register struct dinode *pf;
	static char sbuf[512];
	int *c , fs;

	char *mtm, *pmode();

	hflg = 0;
	bread((long)(2+(i-1)/INOPB), sbuf, 512);
	pf = (struct dinode *)&sbuf[((i-1)%INOPB)*(sizeof (struct dinode))];
	for(n = 0; n < nof; n++) {
		ts = &tab[n];
		if(ts->dv != adv)continue;
		if(ts->in != i)continue;
		if(hflg == 0) {
			fs = pf->di_mode & 020000;
			printf("\nInode    Mode   Lk   Uid  Gid  %s   Modification    Filename\n",
				fs ? "Maj,Min" : "   Size");
			printf("%5d %10.10s%2d%6d%5d  ", i, pmode(pf->di_mode),
				pf->di_nlink, pf->di_uid, pf->di_gid);
			if(fs)
				printf("%3d,%3d", pf->di_addr[2], 
					pf->di_addr[1]);
			else	{
				printf("%7D", pf->di_size);
			}
			mtm = ctime(&pf->di_mtime);
			printf("  %2.2s-%3.3s-%2.2s %5.5s  %s\n",
				mtm+8, mtm+4, mtm+22, mtm+11, mknm(s));
			flush();
			hflg = 2;
		}

		printf("       %-8.8s%8d%4d  Proc:%6d  For: ",ts->who,ts->uid,
			ts->gid,ts->pid);
		if(ts->flg & FREAD)printf("Read");
		if(ts->flg & FWRITE) {
			if(ts->flg & FREAD)printf(", ");
			printf("Write");
		}
		if(ts->flg & 0200)printf("Working Directory\n");
		else    printf(", FD=%2d  Off:%7D\n",ts->fd, ts->offset);
		ts->dv = -1;
		flush();
	}

	hflg = ilist;
	while(*hflg != -1)
		if(*hflg == i){
				c = hflg+1;
				while((*hflg++ = *c++) != -1);
				break;
			  }
			else    hflg++;
	flush();
	if(ilist[0] == -1)return(-1);
	return(0);
}


char    *mknm(s)
register char *s;
{
	static char nbuf[80];
	register char *t , *p;

	t = nbuf;
	p = filesys;
	while(*t++ = *p++);
	t--;
	if(t == &nbuf[1]) t--;
	while(*t++ = *s++);
	return(nbuf);
}



eql(s,t)
register char *s , *t;
{
	while(*s == *t++)
		if(*s++ == 0)return(1);
	return(0);
}


disk()
{
	int fd;

	chdir("/dev");
	if((fd = open("/etc/mnttab",0)) == -1) {
		printf("Unknown\n");
		return(1);
	}

	printf("Device       Free   Free Inodes    Name\n");
	while(read(fd,&mnt,sizeof mnt) == sizeof mnt) {
		if(mnt.mt_dev[0] == 0)continue;
		if(mnt.mt_filsys[0] == 0)continue;
		if((fi = open(mnt.mt_dev,0)) == -1)continue;
		sync();
		lseek(fi, 512L, 0);
		if(read(fi,&sblock,sizeof (sblock)) == sizeof (sblock)){
			printf("/dev/%-6.6s%6D%10u        %-10.10s\n",
				mnt.mt_dev, sblock.s_tfree,
				sblock.s_tinode,mnt.mt_filsys);
		}
		close(fi);
	}
	printf("\n\n");
	close(fd);
	return(0);
}



prheadr(){
	register char *s;
	int fdb;
	long dkt[32];
	register short i;

	s = ctime(&systime);


	lseek(mm, (long)(nl[3].value), 0);
	read(mm, &sysinfo, sizeof (struct sysinfo));
	lseek(mm, (long)(nl[5].value), 0);
	read(mm, &utsname, sizeof (struct utsname));
	uptime = sysinfo.cpu[CPU_IDLE] + sysinfo.cpu[CPU_USER] +
		sysinfo.cpu[CPU_KERNAL] + sysinfo.cpu[CPU_WAIT];
	uptime /= 60;
	if(!coreflg){
		printf("\n%s %s %s \"%s\" System status at %5.5s, ",
			utsname.nodename, utsname.release, utsname.sysname,
			utsname.machine, s + 11);
		printf("%2.2s-%3.3s-%2.2s Up: %s\n", s+8, s+4, s+22, tc(uptime,1));
	}	else	{
		printf("\n%s %s %s Crash/Dump System status at %5.5s, ",
			utsname.nodename, utsname.release, utsname.sysname,
			utsname.machine, s + 11);
		printf("%2.2s-%3.3s-%2.2s\n", s+8, s+4, s+22);
		printf("\nCorefile: %s\t\t\tSwapfile: %s\n", core, SWPDV);
	}

	flush();
}



char *oper(pp)
struct proc *pp;
{
	register p, bp;
	register char *s;

	p = pdb.p_cpu;
	p =& 0377;
	bp = pdb.p_nice + p/16 - NZERO;
	p = pdb.p_pri;

	if(p == PSLEP) s = "Sl";
	else  if(p == PWAIT) s = "Wa";
	  else  if(p == PPIPE) s = "Pp";
	    else  if(p == TTOPRI) s = "To";
	      else  if(p == TTIPRI) s = "Ti";
	        else  if(p == PRIBIO+1) s = "Dw";
	          else  if(p == PRIBIO) s = "Dk";
	            else  if(p == PINOD) s = "In";
	              else  if(p == PSWP) s = "Sw";
	                else  if(p == 23) s = "Rj";
			  else	if(p == PEXEC) s = "Xw";
	                    else  if(p-bp == PUSER) s = "Us";
			      else  if(p == PIDLE) s = "Id";
				else s = "??";
	if(p-bp == PUSER && *s != 'U')s = "??";
	return(s);
}



char *pmode(m)
register m;
{
	register lcnt;
	register char *ret;
	static char pmod[16];

	ret = pmod;
	cps(ret, "----------");
	ret =+ 9;
	lcnt = 3;
	while(lcnt--){
		if(m &   01)*ret = 'x';
		ret--;
		if(m &   02)*ret = 'w';
		ret--;
		if(m &   04)*ret = 'r';
		ret--;
		m =>> 3;
	}
	if(m & 01) ret[9] = 't';
	if(m & 02) ret[6] = 's';
	if(m & 04) ret[3] = 's';
	m =>> 3;
	m =& 06;
	if(m == 02) *ret = 'c';
	else if(m == 04) *ret = 'd';
	     else if(m == 06) *ret = 'b';
	return(ret);
}





prcom(fd)
{
	register int *ip;
	register char *buf, *t;
	char *cp;
	int lim;
	int i;

	buf = &finode[NINDE-INOPB];

	i = 10;
	lim = 508;
	while(i--){
		if(read(fd, buf, 512) != 512){
			printf(" ????");
			return;
		}
		for(ip = &buf[lim]; ip > buf; )
			if(*--ip == -1 || *ip == 0){
				buf = (char *)(ip+1);
				if(*buf == 0)
					buf++;
				for(t = buf; buf < &finode[NINDE]; buf++)
					if(*buf < ' ' || *buf > '~')
						*buf = ' ';
				while(--buf >= t)
					if(*buf != ' ')break;
				*++buf = 0;
				buf = t;
				while(*buf == ' ' && *buf)
					buf++;
				t = buf;
				if((extflag & 2048) == 0){
					while(*buf && *buf != ' ')
						if(*buf++ == '/')
							t = buf;
					buf = t;
					if(extflag & 256) cp = " %.6s";
					else cp = " %.9s";
				} else cp = " %s";
				if((extflag & 16384) == 0){
					while(*buf && *buf != '=')
						buf++;
					if(*buf){
						while(buf > t && *buf != ' ')
							buf--;
						*buf = 0;
					}
					buf = t;
				}
				printf(cp, buf);
					return;
			}
		lim = 510;
		lseek(fd, -1024L, 1);
		buf =- 512;
	}
	printf(" ? > 5120 chars");
	return;
}



char *mkrm(s)
register char *s;
{
	register char *t, *p;
	static char rmb[8];

	p = s;
	t = rmb;
	if(*s == 'r' && *(s+1) == 'm' &&
	   *(s+2) >= '0' && *(s+2) <= '9')*t++ = 'r';
	while(*t++ = *s++);
	if(stat(rmb, &st))return(p);
	return(rmb);
}



flush(){}
