/*
 * John Buck -- Print table of system resource utilization at the current
 *	moment.  Not the use of phys().  Could be replaced by a seek/read
 *	but at speed penalty.  Also, clists won't work right if data is
 *	read, since they are constantly being updated (even as the stats
 *	from this program are being printed!)
 */
#define	EMAPSIZ	15
#include <sys/types.h>
#include <sys/param.h>
#include	<sys/callo.h>
#include	<sys/mount.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/text.h>
#include <sys/var.h>
#include <sys/tty.h>
#include <a.out.h>

int mflg = 0;
struct nlist	nl[16];
struct var v;
short	mem;

main(argc, argv)
int argc;
char **argv;
{
	nice(-10);
	strcpy(nl[0].n_name, "_buf");
	strcpy(nl[1].n_name, "_file");
	strcpy(nl[2].n_name, "_inode");
	strcpy(nl[3].n_name, "_proc");
	strcpy(nl[4].n_name, "_text");
	strcpy(nl[5].n_name, "_coremap");
	strcpy(nl[6].n_name, "_swapmap");
	strcpy(nl[7].n_name, "_callout");
	strcpy(nl[8].n_name, "_mount");
	strcpy(nl[9].n_name, "_cfreeli");
	strcpy(nl[10].n_name, "_cfree");
	strcpy(nl[11].n_name, "_execmap");
	strcpy(nl[12].n_name, "_v");
	nlist("/unix", nl);
	if (nl[0].n_type <= 0) {
		printf("Can not obtain symbol table information\n");
		exit(1);
	}
	if(argc > 1 && *argv[1] == '-'){
		mflg++;
		argv++;
		argc--;
	}

	printf(" Clists     Files    Inodes    Iblks    Procs   Texts   Timers   Mounts\n");
	if ((mem = open(argc > 1?argv[1]:"/dev/mem", 0)) < 0) {
		printf("Can not open memory map device\n");
		exit(2);
	}
	lseek(mem, (long)(nl[12].n_value), 0);
	read(mem, &v, sizeof (struct var));
	clists();
	files();
	inodes();
	procs();
	texts();
	timers();
	mounts();
	printf("\n\n                    Sys Adr. Bufs    Non-adr. Bufs\n");
	printf(    "                    Busy Drty Tot    Busy Drty Tot\n");
	bufs();
	printf("\n\n");
	coremap();
	swapmap();
	execmap();
	close(mem);
	exit(0);
}

clists()
{
	register short j;
	register struct cblock *cflist;
	register int adjust;
	struct cblock *tmplist;
	if(phys(6, 128, (nl[10].n_value >> 6) & 01777)){
		printf("???/???   ");
		return;
	}
	lseek(mem, (long)(nl[9].n_value), 0);
	read(mem, &tmplist, 2);
	cflist = tmplist;
	adjust = (0140000 + (nl[10].n_value & 077)) - nl[10].n_value;
	j = 0;
	if(cflist){
		cflist = (char *)(cflist) + adjust;
		for(j = 1; cflist->c_next; cflist = (char *)(cflist->c_next) + adjust)
			j++;
	}
	printf("%3d/%3d   ", v.v_clist - j, v.v_clist);
	return;
}

files()
{
	register short i, j;
	register struct file *pf;

	if(phys(6, 128,(nl[1].n_value >> 6) & 01777) == -1){
		printf("???/???   ");
		return;
	}
	pf = (struct file *)((char *)(0140000) + (nl[1].n_value & 077));
	for(j = 0, i = v.v_file; i >= 0; i--, pf++)
		if(pf->f_count)
			j++;
	printf("%3d/%3d   ", j, v.v_file);
	return;
}
inodes()
{
	register short i, j;
	register struct inode *pi;
	short iblk;

	if(phys(6, 128,(nl[2].n_value >> 6) & 01777) == -1){
		printf("???/???  ???/???  ");
		return;
	}
	pi = (struct inode *)((char *)(0140000) + (nl[2].n_value & 077));
	for(iblk = 0, j = 0, i = v.v_inode; i >= 0; i--, pi++)
		if(pi->i_number){
			j++;
			if(pi->i_flag & IADDR)
				iblk++;
		}
	printf("%3d/%3d  ", j, v.v_inode);
	printf("%3d/%3d  ", iblk, v.v_iblk);
	return;
}
procs()
{
	register short i, j;
	register struct proc *pp;

	if(phys(6, 128,(nl[3].n_value >> 6) & 01777) == -1){
		printf("???/???   ");
		return;
	}
	pp = (struct proc *)((char *)(0140000) + (nl[3].n_value & 077));
	for(j = 0, i = v.v_proc; i >= 0; i--, pp++)
		if(pp->p_stat)
			j++;
	printf("%3d/%3d   ", j, v.v_proc);
	return;
}
texts()
{
	register short i, j;
	register struct text *pt;

	if(phys(6, 128,(nl[4].n_value >> 6) & 01777) == -1){
		printf("??/??   ");
		return;
	}
	pt = (struct text *)((char *)(0140000) + (nl[4].n_value & 077));
	for(j = 0, i = v.v_text; i >= 0; i--, pt++)
		if(pt->x_iptr)
			j++;
	printf("%2d/%2d   ", j, v.v_text);
	return;
}
timers()
{
	register short j;
	register struct callo *pc;

	if(phys(6, 128,(nl[7].n_value >> 6) & 01777) == -1){
		printf(" ??/??   ");
		return;
	}
	pc = (struct callo *)((char *)(0140000) + (nl[7].n_value & 077));
	for(j = 0; j < v.v_call; pc++,j++)
		if(pc->c_func == 0)
			break;
	printf(" %2d/%2d   ", j, v.v_call);
	return;
}
mounts()
{
	register short i, j;
	register struct mount *pm;

	if(phys(6, 128,(nl[8].n_value >> 6) & 01777) == -1){
		printf(" ??/??   ");
		return;
	}
	pm = (struct mount *)((char *)(0140000) + (nl[8].n_value & 077));
	for(i = v.v_mount; i >= 0; i--, pm++)
		if(pm->m_flags != MFREE)
			j++;
	printf(" %2d/%2d   ", j, v.v_mount);
	return;
}
bufs()
{
	register short i, j;
	static short bcnt[2];
	static short dcnt[2];
	register struct buf *pb;

	if(phys(6, 128,(nl[0].n_value >> 6) & 01777) == -1){
		printf("                     ?? + ?? /??     ?? + ?? / ??   ");
		return;
	}
	pb = (struct buf *)((char *)(0140000) + (nl[0].n_value & 077));
	bcnt[0] = bcnt[1] = dcnt[0] = dcnt[1] = 0;
	for(i = v.v_buf + v.v_sabuf; i >= 0; i--, pb++){
		j = ((paddr(pb)) >= (0140000L));
		if(pb->b_flags & B_BUSY)
			bcnt[j]++;
		if(pb->b_flags & B_DELWRI)
			dcnt[j]++;
	}
	printf("                     %2d + %2d / %2d     %2d + %2d / %2d   ",
		bcnt[0], dcnt[0],v.v_sabuf, bcnt[1], dcnt[1], v.v_buf);
	return;
}
coremap()
{
	register ushort i, j;
	register ushort *pi;
	if(phys(6, 128,(nl[5].n_value >> 6) & 01777) == -1){
		printf("Coremap area unmappable\n");
		return;
	}
	pi = (ushort *)((char *)(0140000) + (nl[5].n_value & 077));
	pi++;
	pi++;
	for(i = j = 0; j < v.v_cmap; j++, pi++,pi++){
		if(*pi == 0)
			break;
		i += *pi;
	}
	if(mflg)
		map((ushort *)((char *)(0140000) + (nl[5].n_value & 077))+2,
			v.v_cmap*2-2, "core", "%8O\t%6u\n", 4);
	printf("Phys. Mem. Free:  %dKb  in %d out of %d pieces\n",
		i >> 4, j, v.v_cmap);
}
swapmap()
{
	register ushort i, j;
	register ushort *pi;
	if(phys(6, 128,(nl[6].n_value >> 6) & 01777) == -1){
		printf("Swapmap area unmappable\n");
		return;
	}
	pi = (ushort *)((char *)(0140000) + (nl[6].n_value & 077));
	pi++;
	pi++;
	for(i = j = 0; j < v.v_smap; j++, pi++,pi++){
		if(*pi == 0)
			break;
		i += *pi;
	}
	if(mflg)
		map((ushort *)((char *)(0140000) + (nl[6].n_value & 077))+2,
			v.v_smap*2-2, "swap", "%7DB\t%6u\n", 1);
	printf("Swap space free:  %4dKb (%u blocks) in %d out of %d pieces\n",
		i >> 1 , i, j, v.v_smap);
}
execmap()
{
	register ushort i, j;
	register ushort *pi;
	if(phys(6, 128,(nl[11].n_value >> 6) & 01777) == -1){
		printf("Execmap area unmappable\n");
		return;
	}
	pi = (ushort *)((char *)(0140000) + (nl[11].n_value & 077));
	pi++;
	pi++;
	for(i = j = 0; j < EMAPSIZ; j++, pi++,pi++){
		if(*pi == 0)
			break;
		i += *pi;
	}
	if(mflg)
		map((ushort *)((char *)(0140000) + (nl[11].n_value & 077))+2,
			EMAPSIZ*2-2, "exec", "%7DB\t%6u\n", 1);
	printf("Exec space free:  %4dKb (%u blocks) in %d out of %d pieces\n",
		i >> 1 , i, j, EMAPSIZ);
}

map(mp, sz, what, format, shift)
int mp[];
register int sz;
register shift;
char *what, *format;
{
	register int i;
	long adr;

	printf("\nMemory allocation table for %s:\n", what);
	printf("   Start	  Size (K-bytes)\n");
	for(i = 0; i < sz; i =+ 2){
		if(mp[i] == 0)continue;
		if(shift != 1) adr = (long)(mp[i+1]) << 6L;
		else	adr = (long)(mp[i+1]) & 0177777L;
		printf(format, adr, mp[i] >> shift);
	}
}
