static char SCCS_ID [] = "@(#)pstat.c    	1.4	 16:23:21 - 82/02/12 ";
/*
 * Print system stuff
 */

#define mask(x) (x&0377)
#include <a.out.h>
#include <sys/local.h>
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/tty.h>
#include <sys/inode.h>
#include <sys/text.h>
#include <sys/proc.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/file.h>

char	*fcore	= "/dev/mem";
char	*fnlist	= "/unix";
int     mem;
char    vduaddr[256];

struct nlist setup[] = {
#ifdef DEC
#define	SINODE	0
	"_inode", 0, 0,
#define	STEXT	1
	"_text", 0, 0,
#define	SPROC	2
	"_proc", 0, 0,
#define	SDH	3
	"_dh11", 0, 0,
#define	SNDH	4
	"_ndh11", 0, 0,
#define	SKL	5
	"_kl11", 0, 0,
#define	SFIL	6
	"_file", 0, 0,
#else
#define X_INODE   0
      { "inode"  },
#define X_NINODE  1
      { "ninode" },
#define X_TEXT    2
      { "text"   },
#define X_NTEXT   3
      { "ntext"  },
#define X_PROC    4
      { "proc"   },
#define X_NPROC   5
      { "nproc"  },
#define X_VDU      6
      { "vdu"    },
#define X_NVDU     7
      { "nvdu"   },
#define X_FILE    8
      { "file"   },
#define X_NFILE   9
      { "nfile"  },
#define X_VDUADDR 10
      { "vduaddr"},
#endif
      { "" },
};
struct  inode *kinode;  /* pointer to the inode table in the kernel */
int     ninode;         /* size of inode table in the kernel */
struct  inode *inode;

struct  proc *kproc;    /* pointer to the proc table in the kernel */
int     nproc;          /* size of proc table in the kernel */
struct  proc *proc;

struct  text *ktext;    /* pointer to the text table in the kernel */
int     ntext;          /* size of text table in the kernel */
struct  text *text;

struct  file *kfile;    /* pointer to the file table in the kernel */
int     nfile;          /* size of file table in the kernel */
struct  file *file;

struct  tty *kvdu;    /* pointer to the vdu table in the kernel */
int     nvdu;          /* size of vdu table in the kernel */
struct  tty *vdu;

int	inof;
int	txtf;
int	prcf;
int	ttyf;
int	usrf;
long	ubase;
int	filf;
int	allflg;

main(argc, argv)
char **argv;
{

	while (--argc && **++argv == '-') {
		while (*++*argv)
		switch (**argv) {

		case 'a':
			allflg++;
			break;

		case 'i':
			inof++;
			break;

		case 'x':
			txtf++;
			break;
		case 'p':
			prcf++;
			break;

		case 't':
			ttyf++;
			break;

		case 'u':
			if (--argc == 0)
				break;
			usrf++;
			ubase = xatoi(*++argv);
			break;

		case 'f':
			filf++;
			break;
		}
	}
	if (argc>0)
		fcore = argv[0];
	if ((mem = open(fcore, 0)) < 0) {
		printf("Can't find %s\n", fcore);
		exit(1);
	}
	if (argc>1)
		fnlist = argv[1];
	nlist(fnlist, setup);
	if (setup[X_INODE].n_type == -1) {
		printf("no namelist\n");
		exit(1);
	}
	if (inof)
		doinode();
	if (txtf)
		dotext();
	if (ttyf)
		dotty();
	if (prcf)
		doproc();
	if (usrf)
		dousr();
	if (filf)
		dofil();
}

doinode()
{
	register struct inode *ip;
	register int nin, loc;

	nin = 0;
	/*
	 * Find out how big the inode table is
	 */
	lseek(mem, (long)setup[X_NINODE].n_value, 0);
	read(mem, (char *)&ninode, sizeof(ninode));
	/*
	 * Locate inode table
	 */
	lseek(mem, (long)setup[X_INODE].n_value, 0);
	read(mem, (char *)&kinode, sizeof(kinode));
	inode = (struct inode *) malloc(ninode*sizeof(struct inode));
	lseek(mem, (long)kinode, 0);
	read(mem, (char *)inode, ninode * sizeof(struct inode));
	for (ip = &inode[0]; ip < &inode[ninode]; ip++)
		if (ip->i_count)
			nin++;
	printf("%d active inodes\n", nin);
	printf("   LOC  FLAGS  CNT DEVICE   INO   MODE NLK UID  SIZE/DEV\n");
	loc = kinode;
	for (ip = &inode[0]; ip < &inode[ninode]; ip++, loc += sizeof(inode[0])) {
		if (ip->i_count == 0)
			continue;
		printf("%7.1x ", loc);
		putf(ip->i_flag&ILOCK, 'L');
		putf(ip->i_flag&IUPD, 'U');
		putf(ip->i_flag&IACC, 'A');
		putf(ip->i_flag&IMOUNT, 'M');
		putf(ip->i_flag&IWANT, 'W');
		putf(ip->i_flag&ITEXT, 'T');
		printf("%4d", ip->i_count&0377);
		printf("%3d,%3d", major(ip->i_dev), minor(ip->i_dev));
		printf("%6l", ip->i_number);
		printf("%7o", ip->i_mode);
		printf("%4d", ip->i_nlink);
		printf("%4d", ip->i_uid);
		if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR)
			printf("%6d,%3d", major(ip->i_un.i_rdev), minor(ip->i_un.i_rdev));
		else
			printf("%10ld", ip->i_size);
		printf("\n");
	}
	free(inode);
}

putf(v, n)
{
	if (v)
		printf("%c", n);
	else
		printf(" ");
}

dotext()
{
	register struct text *xp;
int     ntx;
	register loc;

	/*
	 * Find out how big the text table is
	 */
	lseek(mem, (long)setup[X_NTEXT].n_value, 0);
	read(mem, (char *)&ntext, sizeof(ntext));
	/*
	 * Locate text table
	 */
	lseek(mem, (long)setup[X_TEXT].n_value, 0);
	read(mem, (char *)&ktext, sizeof(ktext));
	text = (struct text *) malloc(ntext*sizeof(struct text));
	lseek(mem, (long)ktext, 0);
	read(mem, (char *)text, ntext * sizeof(struct text));
	ntx = 0;
	for (xp = &text[0]; xp < &text[ntext]; xp++)
		if (xp->x_iptr!=NULL)
			ntx++;
	printf("%d text segments\n", ntx);
	printf("   LOC FLAGS DADDR  CADDR SIZE   IPTR  CNT CCNT\n");
	loc = ktext;
	for (xp = &text[0]; xp < &text[ntext]; xp++, loc+=sizeof(text[0])) {
		if (xp->x_iptr == NULL)
			continue;
		printf("%7.1x", loc);
		printf(" ");
		putf(xp->x_flag&XTRC, 'T');
		putf(xp->x_flag&XWRIT, 'W');
		putf(xp->x_flag&XLOAD, 'L');
		putf(xp->x_flag&XLOCK, 'K');
		putf(xp->x_flag&XWANT, 'w');
		printf("%5u", xp->x_daddr);
		printf("%7.1x", xp->x_caddr);
		printf("%5d", xp->x_size);
		printf("%8.1x", xp->x_iptr);
		printf("%4d", xp->x_count&0377);
		printf("%4d", xp->x_ccount);
		printf("\n");
	}
	free(text);
}

doproc()
{
	register struct proc *pp;
	register loc, np;

	/*
	 * Find out how big the proc table is
	 */
	lseek(mem, (long)setup[X_NPROC].n_value, 0);
	read(mem, (char *)&nproc, sizeof(nproc));
	/*
	 * Locate proc table
	 */
	lseek(mem, (long)setup[X_PROC].n_value, 0);
	read(mem, (char *)&kproc, sizeof(kproc));
	proc = (struct proc *) malloc(nproc*sizeof(struct proc));
	lseek(mem, (long)kproc, 0);
	read(mem, (char *)proc, nproc * sizeof(struct proc));
	np = 0;
	for (pp = &proc[0]; pp < &proc[nproc]; pp++)
		if (pp->p_stat)
			np++;
	printf("%d processes\n", np);
	printf("   LOC S  F  PRI SIGNAL UID TIM CPU NI  PGRP   PID  PPID ADDR SIZE  WCHAN   LINK  TEXTP  CLKT\n");
	for (loc=kproc,pp = &proc[0]; pp<&proc[nproc]; pp++,loc+=sizeof(proc[0])) {
		if (pp->p_stat==0 && allflg==0)
			continue;
		printf("%6x", loc);
		printf("%2d", pp->p_stat);
		printf("%3o", pp->p_flag);
		printf("%5d", pp->p_pri);
		printf("%7o", pp->p_sig);
		printf("%4d", pp->p_uid&0377);
		printf("%4d", pp->p_time&0377);
		printf("%4d", pp->p_cpu&0377);
		printf("%3d", pp->p_nice);
		printf("%6d", pp->p_pgrp);
		printf("%6d", pp->p_pid);
		printf("%6d", pp->p_ppid);
		printf("%5x", pp->p_addr);
		printf("%5x", pp->p_size);
		printf("%7x", pp->p_wchan);
		printf("%7x", pp->p_link);
		printf("%7x", pp->p_textp);
		printf(" %u", pp->p_clktim);
		printf("\n");
	}
	free(proc);
}

dotty()
{
	register struct tty *tp;
	register char *mesg;

#ifdef DEC
	printf("1 kl11\n");
	lseek(fc, (long)setup[SKL].value, 0);
	read(fc, (char *)dh11, sizeof(dh11[0]));
#endif
	mesg = " # RAW CAN OUT   MODE   ADDR   DEL COL  STATE   PGRP\n";
#ifdef DEC
	ttyprt(0, &dh11[0]);
	if (setup[SNDH].type == -1)
		return;
	lseek(fc, (long)setup[SNDH].value, 0);
	read(fc, (char *)&ndh, sizeof(ndh));
#else
	/*
	 * Find out how big the vdu table is
	 */
	lseek(mem, (long)setup[X_NVDU].n_value, 0);
	read(mem, (char *)&nvdu, sizeof(nvdu));
	/*
	 * Locate vdu table
	 */
	lseek(mem, (long)setup[X_VDU].n_value, 0);
	vdu = (struct tty *) malloc(nvdu*sizeof(struct tty));
#endif
	read(mem, (char *)vdu, nvdu * sizeof(struct tty));
	lseek(mem, (long)setup[X_VDUADDR].n_value, 0);
	read(mem, (char *)vduaddr, nvdu );
	printf("%d ports\n", nvdu);
	printf(mesg);
	for (tp = &vdu[0]; tp < &vdu[nvdu]; tp++)
		ttyprt(tp-vdu, tp);
	free(vdu);
}

ttyprt(n, atp)
struct tty *atp;
{
	register struct tty *tp;

	tp = atp;
	printf("%2d", n);
	printf("%4d", tp->t_rawq.c_cc);
	printf("%4d", tp->t_canq.c_cc);
	printf("%4d", tp->t_outq.c_cc);
	printf("%8.1o", tp->t_flags);
	printf("%8.3x", vduaddr[n]);
	printf("%3d", tp->t_delct);
	printf("%4d ", tp->t_col);
	putf(tp->t_state&TIMEOUT, 'T');
	putf(tp->t_state&WOPEN, 'W');
	putf(tp->t_state&ISOPEN, 'O');
	putf(tp->t_state&CARR_ON, 'C');
	putf(tp->t_state&BUSY, 'B');
	putf(tp->t_state&ASLEEP, 'A');
	putf(tp->t_state&XCLUDE, 'X');
	putf(tp->t_state&HUPCLS, 'H');
	printf("%6d", tp->t_pgrp);
	printf("\n");
}

dousr()
{
	union {
		struct	user rxu;
		char	fxu[ctob(USIZE)];
	} xu;
	register struct user *up;
	register i;

	lseek(mem, ctob(ubase), 0);
	read(mem, (char *)&xu, sizeof(xu));
	up = &xu.rxu;
	printf("rsav %x %x\n", up->u_rsav[0], up->u_rsav[1]);
	printf("segflg, error %d, %d\n", up->u_segflg, up->u_error);
	printf("uids %d,%d,%d,%d\n", up->u_uid,up->u_gid,up->u_ruid,up->u_rgid);
	printf("procp %x\n", up->u_procp);
	printf("base, count, offset %x %x %ld\n", up->u_base,
		up->u_count, up->u_offset);
	printf("cdir %x\n", up->u_cdir);
	printf("dbuf %14s\n", up->u_dbuf);
	printf("dirp %1x\n", up->u_dirp);
	printf("dent %d %14s\n", up->u_dent.d_ino, up->u_dent.d_name);
	printf("pdir %x\n", up->u_pdir);
	printf("dseg");
	for (i=0; i<256; i++)
		if( up->u_uisa[i] && 0x40000000 )  /* present bit */
			printf(" %x %9x  ", i, up->u_uisa[i]);
	printf("\n    ");
	printf("\nfile");
	for (i=0; i<8; i++)
		printf("%8x", up->u_ofile[i]);
	printf("\n    ");
	for (i=8; i<16; i++)
		printf("%8x", up->u_ofile[i]);
	printf("\n    ");
	for (i=16; i<NOFILE; i++)
		printf("%8x", up->u_ofile[i]);
	printf("\nargs");
	for (i=0; i<5; i++)
		printf(" %x", up->u_arg[i]);
	printf("\nsizes %x %x %x\n", up->u_tsize, up->u_dsize, up->u_ssize);
	printf("sep %d\n", up->u_sep);
	printf("qsav %x %x\n", up->u_qsav[0], up->u_qsav[1]);
	printf("ssav %x %x\n", up->u_ssav[0], up->u_ssav[1]);
	printf("sigs");
	for (i=0; i<NSIG; i++)
		printf(" %x", up->u_signal[i]);
	printf("\ntimes %ld %ld\n", up->u_utime/60, up->u_stime/60);
	printf("ctimes %ld %ld\n", up->u_cutime/60, up->u_cstime/60);
	printf("ar0   %x\n", up->u_ar0);
/*
	printf("prof");
	for (i=0; i<4; i++)
		printf(" %x", up->u_prof[i]);
*/
	printf("\nintflg %d\n", up->u_intflg);
	printf("ttyp %x\n", up->u_ttyp);
	printf("ttydev %d,%d\n", major(up->u_ttyd), minor(up->u_ttyd));
	printf("comm %14s\n", up->u_comm);
}

xatoi(s)
char *s;
{
	register v;

	v = 0;
	while (*s){
		if( *s >= '0' && *s <= '9'){
			v = (v<<4) + *s++ - '0';
		} else {
			v = (v<<4) + *s++ -'a' + 10;
		}
	}
	return(v);
}

dofil()
{
	register struct file *fp;
	register nf;
	int loc;

	nf = 0;
	/*
	 * Find out how big the file table is
	 */
	lseek(mem, (long)setup[X_NFILE].n_value, 0);
	read(mem, (char *)&nfile, sizeof(nfile));
	/*
	 * Locate file table
	 */
	lseek(mem, (long)setup[X_FILE].n_value, 0);
	read(mem, (char *)&kfile, sizeof(kfile));
	file = (struct file *) malloc(nfile*sizeof(struct file));
	lseek(mem, (long)kfile, 0);
	read(mem, (char *)file, nfile * sizeof(struct file));
	for (fp = &file[0]; fp < &file[nfile]; fp++)
		if (fp->f_count)
			nf++;
	printf("%d open files\n", nf);
	printf("  LOC   FLG CNT   INO    OFFS\n");
	for (fp = &file[0],loc=kfile; fp < &file[nfile]; fp++,loc+=sizeof(file[0])) {
		if (fp->f_count==0)
			continue;
		printf("%7.1x ", loc);
		putf(fp->f_flag&FREAD, 'R');
		putf(fp->f_flag&FWRITE, 'W');
		putf(fp->f_flag&FPIPE, 'P');
		printf("%4d", mask(fp->f_count));
		printf("%8.1x", fp->f_inode);
		printf(" %ld\n", fp->f_un.f_offset);
	}
	free(file);
}
