AUSAM/source/S/du.c

Compare this file to the similar file:
Show the results in this format:

#
#include	<local-system>

/*
 *	Unix disc usage program:
 *		du -s [dir1 .....]	sums in each directory
 *		du -a [dir1 .....]	prints usage for all entries
 *		du -u [name1 .....]	prints usage for users name1 ,...
#indef	AUSAM
 *		du -g [group1 .....]	for each group
#endif
 *		du -s -[ug]		requests total for group/user
 *			K Birman
 */

/*
 *	AUSAM --	remove options ( needs to be restored to former glory )
 */

long	du();
long	pdu();
int	oflush();
#ifndef	AUSAM
struct	{
	char who[10];
	long	owned;
} *nlist;
#endif
int	*table;
long	fsize;
#ifndef	AUSAM
int	nuse;
#endif
unsigned uid;
int	fout;
int	fin;
int	maxword -1;
char	*name;
int	aflg;
int	sflg;
int	uflg;
#ifndef	AUSAM
int	gflg;
#endif
int	restrict;
int	count;
char	**vec;
int	mfile;

struct	mtab {
	char where[32];
	char m_name[32];
} mtab;

#ifndef	AUSAM
int	ulist[256];
#endif

/* list of resident discs: /etc/mtab doesn't mention these */
char	*ress[] {
	"/dev/hp0",
	0
};
char	**res	ress;

main(argc, argv)
char **argv;
{
	char place[10];

	table = sbrk(0);
	if(argc > 1) {
		++argv;
		while(**argv == '-') {
			argc--;
			switch((*argv++)[1]) {
			case 'a':
				aflg++;
				break;
			case 's':
				sflg++;
				break;
#ifndef	AUSAM
			case 'u':
				uflg++;
				break;
			case 'g':
				gflg++;
				break;
#endif
			default:
				type("Unknown option");
				exit(1);
			}
		}
		if(argc > 1) {
			restrict++;
			count = argc;
			vec = argv;
		}
	}
	fout = dup(1);
	signal(2, oflush);
	signal(3, oflush);
#ifndef	AUSAM
	if((uflg == 0 && gflg == 0) || aflg)
#endif
		if(restrict) while(argc-- > 1)
			pdu(*argv++);
		else
			pdu(".");
#ifndef	AUSAM
	else {
		build();
		while(*res)
			dui(*res++);
		mfile = open("/etc/mtab", 0);
		if(mfile > 0) while(read(mfile, &mtab, 64) == 64) {
			append("/dev", mtab.m_name, place, 5, 10);
			dui(place);
		}
	}
	if(sflg && (uflg||gflg))
		ptot();
#endif
	flush();
}

long pdu(s)
{
	long n;

	n = du(s);
	typen(n);
	type(s);
	return(n);
}

typen(n)
long n;
{
	register char *s;
	register int i;
	char *locv();

	s = locv(n);
	i = 0;
	while(*s) {
		putchar(*s++);
		i++;
	}

	while(i++ < 12)
		putchar(' ');
}

type(s)
register char *s;
{
	if(*s == '/' && *(s+1) == '/') s++;
	while(*s)
		putchar(*s++);
	putchar('\n');
}
#ifndef	AUSAM
build()
{
	register int *i;
	for(i = ulist; i<&ulist[256]; *i++ = -1);
	fin = open(gflg ? "/etc/group":"/etc/passwd", 0);
	nlist = sbrk(sizeof *nlist);
	table =+ sizeof *nlist;
	while(getent()) if(useent())
		ulist[uid] = nuse++;
	close(fin);
}
#define	NAME	0
#define	USER	2
#endif
#define	DIR	1
#ifndef	AUSAM
getent()
{
	register int state;
	register char  *s;
	int c;
	state = 0;
	s = name = nlist[nuse].who;
	uid = 0;

	while(c = getchar())
	switch(c) {
	case ':':
		if(!state++) *s++ = 0;
		continue;
	case '\n':
		sbrk(sizeof *nlist);
		table =+ sizeof *nlist;
		nlist[nuse].owned = 0;
		return(1);
	default:
		switch(state) {
		case NAME:
			if(s == &name[9])
				continue;
			*s++ = c;
			break;
		case USER:
			uid = uid*10 + c - '0';
			break;
		}
		continue;
	}
	return(0);
}

useent()
{
	int argc;
	register char **argv, *s, *ss;

	if(restrict == 0) return(1);

	argc = count;
	argv = vec;
	while(argc-- > 1){
		s = *argv++;
		ss = name;
		while(*s == *ss && *s++) ss++;
		if(*ss) continue;
		return(1);
	}
	return(0);
}
#endif

mark(bit)
long bit;
{
	register int word, mask;
	word = (bit>>4);
	if(word > maxword) {
		sbrk((word - maxword)<<1);
		maxword = word;
	}

	mask = 1<<(bit & 017);
	if(table[word] & mask)
		return(1);
	table[word] =| mask;
	return(0);
}
long du(dir)
{
	register int fd, loc;
	long size, total;
	char string[250];
	struct dent {
		int ino;
		char d_name[14];
	} dent;

	if(ftype(dir) != DIR || (fd = open(dir, 0)) < 0)
		return(fsize);
	loc = 0;
	total = fsize;

	while(read(fd, &dent, 16) == 16) {
		loc =+ 16;
		if(dent.ino == 0)
			continue;
		if(dent.d_name[0] == '.' && ((dent.d_name[1] == '.' && dent.d_name[2] == 0) || dent.d_name[1] == 0))
			continue;
		if(fd == 14)
			close(fd);
		append(dir, dent.d_name, string, 15, 50);
		if(ftype(string) == DIR)
			if(sflg == 0) {
				size = pdu(string);
			} else {
				size = du(string);
				if(aflg) {
					typen(size);
					type(string);
				}
			}
		else {
			size = fsize;
			if(aflg) {
				typen(size);
				type(string);
			}
		}
		if(mark(0, dent.ino) == 0)
			total =+ size;
		if(fd == 14) {
			fd = open(dir, 0);
			seek(fd, loc, 0);
		}
	}
	close(fd);
	return(total);
}
#ifndef	AUSAM
dui(disk)
{
	long len;
	int *aadr;
	struct {
		int flags;
		char nlinks;
		char iuid;
		char igid;
		char sizeo;
		int sizel;
		int crap[12];
	} inode;
	register int t, dfile, i;
	int isize;

	type(disk);
	dfile = open(disk, 0);
	if(dfile < 0) return;
	len = 0;
	seek(dfile, 1, 3);
	read(dfile, &isize, 2);
	seek(dfile, 2, 3);
	isize =<< 4;

	while(isize--) {
		read(dfile, &inode, 32);
		if((inode.flags & 0100000) == 0) continue;
		if(restrict) {
			if(gflg && ulist[t = inode.igid] < 0)
				continue;
			else if(uflg && ulist[t = inode.iuid] < 0)
				continue;
		} else
			if(gflg)
				t = inode.igid;
			else
				t = inode.iuid;
		i = inode.sizeo;
		len = ((inode.sizel>>9) & 0177) + (i<<7);
		if(inode.sizel & 0777) len++;
		if(inode.flags & 010000) {
			aadr = inode.crap;
			for(i = 0; i<8; i++)
				if(*aadr++)
					len++;
		}
	nlist[ulist[t]].owned =+ len;
	}
	close(dfile);
	if(sflg)
		return;
	ptot();
}
#endif

ftype(what)
{
	register int is0, *p, f;
	struct	{
		char major;
		char minor;
		int inumber;
		int iflags;
		char nlinks;
		char suid;
		char sgid;
		char size0;
		int size1;
		int addr[8];
		long time[2];
	} status;

	if(stat(what, &status) == -1)
		return(0);
	is0 = status.size0;
	fsize = ((status.size1>>9)&0177) + (is0<<7);
	if(status.size1 & 0777) fsize++;
	f = status.iflags;
	if(f & 010000) {
		p = status.addr;
		do
			if(*p) fsize++;
		while(p++ < &status.addr[7]);
	}
	if((f & 060000)==040000)
		return(DIR);
	return(0);
}
append(s1, s2, s3, l2, l3)
register char *s1, *s2, *s3;
{
	while(*s1)
	if(--l3)
		*s3++ = *s1++;
	else break;

	*s3++ = '/';
	while(--l2 && --l3 && (*s3++ = *s2++));
	*s3 = '\0';
}

oflush()
{
	/* after a ^C or ^P */
	flush();
	exit(0);
}

#ifndef	AUSAM
ptot()
{
	register int i,t;
	for(i = 0; i<256; i++)
		if((t = ulist[i]) >= 0) {
			typen(nlist[t].owned);
			nlist[t].owned = 0;
			type(nlist[t].who);
		}
}
#endif