#include "nfs.h"

trouble()
	{
	snstat(fn,&code,3);
	printf("timeout\n");
	ex(1);
	}

name(p)
char *p;
	{
	bp = buf;
	*bp++= ntype;
	while(*bp++ = *p++);
	}


sendc(c)			/* sends command to file store */
char c;
	{
	nchar = bp - buf;
	if (send(nchar,3) < 0) trouble();
	if(check(c) == 0)return(0);
	exx();
	return(-1);
	}

check(c)
char c;
	{
	int r;
	extern timeout();

	signal(14,timeout); alarm(30);
	if((read(fn,rply,100)) < 0) trouble();
	alarm(0);
	snstat(fn,&r,1);
	if (r != 3) {printf("Illegal format from file store\n"); ex(1);}
	if (*rply == c) return(0);
	return(-1);
	}

send(n,c)
char c;
int n;
	{
	snstat(fn,&c,0);
	return(write(fn,buf,n));
	}


		/* test for a directory  */
dir()
	{
	if ((stat(tp,dirbuf) < 0)||((dirbuf[2] & 060000) != 040000)) return(0);
	sp =+ sz; sp[sff]=ff;
	return(1);
	}

gen()
	{
up:
	if(sp != stack)
		{
		/* get next entry in the directory  */
		do	{
			if (read(sp[sff],dirbuf,dsz) < dsz)
			 	{
				close(sp[sff]);
				sp =- sz;
				goto up;
				}
			} while((dirbuf[0] == 0) || (dirbuf[1] == '.') || (dirbuf[1] == '..'));
		dirbuf[dsz] = 0;
		sp[spos] = append(dirbuf+1,sp[sposx]);
		}
	else
		{
	upx:
		if(xsp == stack)return(0);
		/* a list of titles from File Store is being processed  */
		if(xsp->first == xsp->lst)
			{
			xsp--; nxt = xsp->lst;
			goto upx;
			}
		xsp->pos = append(xsp->first,(xsp-1)->pos);
		xsp->first =+ 14;
		}
	return(nam);
	}


append(ps,pd)
char *ps,*pd;
	{
	if(pd != nam) *pd++ = '/';		/* if at beginning of path
					name do not want '/' */
	while(*pd++ = *ps++);
	return(--pd);
	}
addup(n)
int n;
	{
	int k,s; s=0;
	if (n>0) {for (k=0; k<n; k++) s =+ buf[k];}
	return(s);
	}




qt(ecode) int ecode;			/* send finished transmittiing to file store */
	{
	bp = buf; *bp++ = QUIT;
	sendc(OK);
	flush();
	ex(ecode);
	}

ex(ecode) int ecode;
	{
	flush();
	exit(ecode);
	}

/*  'I' function requires confirmation from user  */

ask()
	{
	char c;

	if(iflag)
		{
		printf("%c %s ?",op,tp);
		if((c = grply()) == 'x')qt(0);		/* get the reply */
		if(c != 'y')return(1);
		}
	return(0);
	}


		/* routine to print status of file whose name is 
		   in buf  */
astat(p) char p;
	{
	int i;

	i = gstat();
	if (i == -1) printf("%s not found\n",tp);
	if (i < 0) return;
	if (p == 't') {printf("%s\n",tp); return;}
	np = ctime(dirbuf->i_modtime);
	*(np+24)=0;
	printf("%c  %7s %s  %s\n",*rply,locv(dirbuf->i_size0,dirbuf->i_size1),np+4,tp);
	}

gstat()		/* get status of file or directory in tp */
		/* returns form gstat:
			0 - file exists;
			1 - directory exists;
			-1 not found;
		*/
	{
	char *p;
	int t, i;

	*bp++ = IF;		/* if name exists get status - else return */
	*bp++ = STATUS;
	*bp++ = FI;
	if(send(bp-buf,3) < 0)trouble();
	if((check(stype)) < 0)
		{
		if((*rply & 0377) == OK)return(-1);	/* not found */
		exx();
		return(-2);
		}

	p = &rply[2];
	for( i = 0;i < 34; i++) 
		{
		dirbuf[i] = *p++; dirbuf[i] = (dirbuf[i] << 8) | (*p++ & 0377);
		}
	t = rply[1];
	p = stat1;
	bp = rply;
	while(*bp++ = *p++);
		/* if a directory mark it  */
	if (t == dtype) rply[0] = 'd';
	else if (t == atype) rply[0] = 'a';
			/* set permissions  */
	for( bp = bp-2; *bp != ' '; bp--)
		{
		if((dirbuf->i_mode & 1) == 0) *bp = '-';
		dirbuf->i_mode =>> 1;
		}
	return((t == dtype) ? 1 : 0);
	}




compar(ap1,ap2)
char *ap1,*ap2;
	{
	register char *p1,*p2;
	register int k;
	int j;

	p1 = ap1; p2 =ap2;
	for(k = 0;k<14; k++)
		if((j = *p1 - *p2++) || *p1++ ==0)
			return(j);
	return(0);
	}



rd(op1) char op1;		/* read data from spider
				put on file for 'r' or 'u' and build list for 't' */
	{
	int j, i;
	extern timeout();
	char *ps;

	if(sendc(READ))return(-1);
	sum = 0; length = 0;
	do	{
		signal(14,timeout); alarm(30);
		if((nchar = read(fn,buf,512)) < 0) trouble();
		alarm(0);
/*
		sum =+ addup(nchar); length =+ nchar;
*/
		if (nchar != 0)
			{
			if (op1 == 't')
				{
				for(i =0; i< nchar; i=+ 16)
					{
					if (buf[4] == '.') continue;
			/* get more space if necessary  */
					if(nxt >= last){sbrk(512); last =+ 512;}
					ps = &buf[i+4];
					for(j =0; j <12; j++)*nxt++ = *ps++;
					*nxt++ = 0; *nxt++ = 0;
					}
				}
			else wchar = write(ff,buf,nchar);
			}
		snstat(fn,&code,1);
		}
	while((nchar != 0)&&(code < 2));
	if ((code != 2) && (code != 4))
		{
		printf("Illegal format from file store\n");qt(1);
		}
	if(check(OK) < 0) {exx(); return(-1);}
	return(0);
	}

/* determine if directory. arg true if to put contents on stack.
 * return -1 if not define, 0 if file, 1 if directory, 2 if xflag and directory.
 */

xdir(m) int m;		/* determine if file or directory in file store  */
	{
	char a;
	int i;

		i = gstat();		/* get status */
		name(fsp);
		if(i != 1)return(0);	/* not a directory */
	if (xflag) return(2);
	xsp++;
	xsp->first = nxt;		/* keep first name in stack  */
	*bp++ = LIST;		/* get list of tiles */
	if(rd('t'))
		{xsp--; return(-1);}
	if (m) xsp->lst = nxt;		/* get end of list */
	else xsp--;
	return(1);
	}


grply()		/* routine to return first non-blank character reply */
	{
	char *ip;
	if(read(0,rply,64) <=0)return(1);
	ip = rply; while(*ip == ' ')ip++;
	return(*ip);
	}

spstat()
	{
	int i;

	append(".a",sp[spos]);
	name(fsp);
	if (i = gstat())
		{
		if (i != -1) exx();
		printf("%s  is not an account\n",tp);
		return;
		}
	printf("limit %5s ",locv(dirbuf->i_addr[4],dirbuf->i_addr[5]));
	dpsub(&dirbuf->i_addr[4],&dirbuf->i_addr[2]);
	printf("used %5s ",locv(dirbuf->i_addr[4],dirbuf->i_addr[5]));
	printf("%s\n",tp);
	}

					/*trap on alarm*/
timeout() {;}
