
#include "sys/param.h"
#include "sys/inode.h"
#include "sys/stat.h"

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

struct stat statb;

struct		{
	char rfsys[32];
	char rdev[32];
} rmount;

struct mount {
	char fsys[32];
	char dev[32];
} mount[NMOUNT];
struct inode inode[NINODE];

int	devcnt = 0;
int	devtab[NMOUNT];
char	*pathp[NINODE];
char	paths[NINODE][128];
char	*argv[NINODE+8];
int	argc;
char	argbuf[NINODE+8][16];
int	inos[NINODE];

char	*core = "/dev/mem";
char	*os = "/unix";
int	mem;
int	nflg = 0;
int	vflg = 0;
int	oldstdo, oldstdi;
int	ni = 0;
char	buf[512];
char	*cpn();

main(c, v)
char **v;
{
	register struct inode *ip;
	register j;

	j = getgid();
	if(j != 0 && j != 3 && j != 2){
		printf("Access denied.\n");
		exit(1);
	}

	oldstdo = dup(1);
	oldstdi = dup(0);
	while(--c){
		if(*(*++v) != '-');
		else	switch(*++*v){
	case 'c':
		if(c > 1){
			c--;
			core = *++v;
		}
		break;

	case 'u':
		if(c > 1){
			c--;
			os = *++v;
		}
		break;
	case 'n':
		nflg++;
		break;
	case 'v':
		vflg++;
		break;
		}
	}
	cps(&nl[0], "_inode");
	nlist(os, nl);
	if(nl[0].type < 0){
		printf("No namelist.\n");
		exit(1);
	}
	if((mem = open(core, 0)) == -1){
		printf("Can not open \"%s\"\n", core);
		exit(2);
	}
	lseek(mem, (long)(nl[0].value), 0);
	read(mem, inode, sizeof inode);
	if(nflg == 0){
		getmount();
		getnames();
	}
	printf("Inode   HomDev    Mode    Link     Uid   Gid  Siz/Mj-Mn  Filename\n");
	for(ip = inode; ip < &inode[NINODE]; ip++){
		if(ip->i_number == 0)continue;
		printf("I%-5d: %2d,%-2d  Md:%6o Ln:%-3d  U:%-5d G:%-3d  ",
			ip->i_number, (ip->i_dev >> 8) & 0377,
			ip->i_dev & 0377, ip->i_mode, ip->i_nlink,
			ip->i_uid, ip->i_gid);
		if((j = (ip->i_mode & 060000)) && j != 040000)
			printf("%3d,%3d  ", (dev_t)(ip->i_un.i_rdev >> 8) & 0377,
				(dev_t)(ip->i_un.i_rdev) & 0377);
		else	printf("%7D  ", ip->i_size);
		printf("%s\n", nflg ? "????????" : pathp[ip-inode]);
	}
	close(mem);
}

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

getnames()
{
	register struct inode *ip;
	register i, j;
	char *device;

	argv[0] = "/staff/john/bin/sncheck";
	argv[1] = "linodes(sncheck)";
	argv[2] = "-i";
	for(i = 0; i < devcnt; i++){
		if(devtab[i] == 0)continue;
		argc = 3;
		if(vflg) printf("%s: %s", argv[1], argv[2]);
		device = mount[i].dev;
		for(ip = inode; ip < &inode[NINODE]; ip++){
			if(ip->i_number == 0)continue;
			if(devtab[i] == (ip->i_dev)){
				argv[argc] = cpn(&argbuf[argc][15], ip->i_number);
				if(vflg) printf(" %s", argv[argc]);
				argc++;
			}
		}
		if(vflg) printf(" %s\n", device);
		if(argc == 3){
			if(vflg) printf("None there.\n");
			continue;
		}
		argv[argc++] = device;
		argv[argc] = 0;
		dofork();
		for(ip = inode; ip < &inode[NINODE]; ip++){
			if(ip->i_number == 0)continue;
			if((ip->i_dev) == devtab[i]){
				for(j = ni-1; j >= 0; j--){
					if(inos[j] == ip->i_number){
						pathp[ip-inode] = paths[j];
						break;
					}
				}
			}
		}
	}
}

char *
cpn(s, n)
register char *s;
register n;
{
	*s = 0;
	while(n){
		*--s = n%10 + '0';
		n /= 10;
	}
	return(s);
}

dofork()
{
	register char *s;
	register i;
	register cnt;
	char *t;
	int w;
	int pvec[2];

	close(0);
	close(1);
	if(pipe(pvec)){
		printf("Pipe creation error\n");
		exit(3);
	}
	if(fork() == 0){
		close(0);
		dup(oldstdi);
		execv(argv[0], argv+1);
		write(2, "Execv of sncheck failed\n", 24);
		exit(4);
	}
	close(1);
	dup(oldstdo);
	cnt = ni;
lp:
	s = buf;
	while((*s = getchar()) != '\n' && *s > 0)s++;
	if(*s < 1){
		close(0);
		dup(oldstdi);
		wait(&w);
		ni = cnt;
		return(0);
	}
	*s = 0;
	s = buf;
	while(*s == ' ')s++;
	if(*s < '0' || *s > '9')goto lp;	/* pipe fluff */
	i = 0;
	while(*s >= '0' && *s <= '9')
		i = i * 10 + (*s++) - '0';
	if(*s != ' ' && *s != '\t')goto lp;
	s++;
	if(*s != '/')goto lp;
	inos[cnt] = i;
	t = paths[cnt];
	cps(t, s);
	cnt++;
	goto lp;
}


getmount()
{
	int fd;
	register int i;
	register char *s, *t;
	char *dtmp;

	if((fd = open("/etc/mtab", 0)) == -1){
		printf("No mount table\n");
		exit(1);
	}

	for(i = 0; read(fd, &rmount, 64) == 64; i++){
		strncpy(mount[i].dev, rmount.rdev, 32);
		strncpy(mount[i].fsys, rmount.rfsys, 32);
		s = dtmp = mount[i].dev;
		if(*s == 0 || mount[i].fsys[0] == 0){
			continue;
		}
		while(*s)s++;
		t = s + 4;
		while(s > dtmp)*t-- = *--s;
		if(t != &dtmp[4])*t-- = 'r';
		*t-- = '/';
		*t-- = 'v';
		*t-- = 'e';
		*t-- = 'd';
		*t = '/';
		if(dtmp != t){
			printf("mtab: %s not in proper format\n", t);
			exit(3);
		}
		if(stat(t, &statb)){
			printf("Can not stat %s\n", t);
			exit(4);
		}
		devtab[i] = statb.st_rdev;
	}
	devcnt = i;
	close(fd);
	getcdevs();
}


getcdevs()
{
	register i;
	register char *s, *t;

	for(i = 0; i < devcnt; i++){
		s = mount[i].dev;
		if(*s == 0){
			continue;
		}
		if(s[6] != 'm' /* && any others */)
			continue;
		while(*s)s++;
		t = s-1;
		while(*t != '/')*s-- = *t--;
		*++t = 'r';
	}

}

