#include "rtunix.h"

read(des,buffer,length)
char *buffer;
{
register struct file *f;
register int l;
int len;
int off, blk;

top;
#ifdef	debug
	_trace("read(%d,%o,%d)",des,buffer,length);
#endif
f = getf(des);

blk = ldiv(f->f_off[0],f->f_off[1],512);
off = ldivr;
len = 0;
switch(f->f_type)
	{
case TTY:
	for (len=0; len<length; )
		{
		l = ttyin();
		if(l == '\r')
			continue;
		if(l >= 'A' && l <= 'Z')
			l =- 'A'-'a';
		buffer[len++] = l;
		if(l == '\n' || l == 032)
			break;
		}
	goto done;

case FILE:
	if(off)
		{
		if(rtread(f->f_chan, blk++, _buff, 0400, 0) == -1)
			if(errwrd)
				seterr(EIO);
			else
				goto done;
		l = 512-off;
		if(l > length)
			l = length;
		move(l, _buff, buffer);
		buffer =+ l;
		len =+ l;
		length =- l;
		dpadd(f->f_off,l);
		}
	if(length > 0)
		{
		if((l = length) & 1)
			++l;
		if((l = rtread(f->f_chan, blk, buffer, l>>1, 0)) == -1)
			if(errwrd)
				seterr(EIO);
			else
				goto done;
		l =<< 1;
		len =+ l;
		dpadd(f->f_off, l);
		}
	break;

default:
	if((l = length) & 1)
		++l;
	l =>> 1;
	rtread(f->f_chan, blk, buffer, l, 0);
	len = length;
	}
done:
#ifdef	debug
	_trace(" return(%d)",len);
#endif
return(len);
}


write(des,buffer,length)
char *buffer;
{
register struct file *f;
register int l;
int len;
int off, blk;

top;
#ifdef	debug
	_trace("write(%d,%o,%d)",des,buffer,length);
#endif
f = getf(des);

blk = ldiv(f->f_off[0],f->f_off[1],512);
off = ldivr;
len = 0;
switch(f->f_type)
	{
case TTY:
	for (len=0; len<length; ++len)
		{
		l = *buffer++;
		if(l == '\n')
			ttyout('\r');
		ttyout(l);
		}
	break;

case FILE:
	if(off)
		{
		rtread(f->f_chan, blk, _buff, 0400, 0);
		l = 512-off;
		if(l > length)
			l = length;
		move(l, buffer, _buff+off);
		rtwrite(f->f_chan, blk++, _buff, 0400, 0);
		buffer =+ l;
		len =+ l;
		length =- l;
		dpadd(f->f_off,l);
		}
	if(length > 0)
		{
		if((l = length) & 1)
			++l;
		l =>> 1;
		rtwrite(f->f_chan, blk, buffer, l, 0);
		len =+ length;
		dpadd(f->f_off, length);
		blk =+ (length+511)/512;
		}
	if(blk > f->f_last)
		f->f_last = blk;
	break;
default:
	if((l = length) & 1)
		++l;
	l =>> 1;
	rtwrite(f->f_chan, blk, buffer, l, 0);
	len = length;
	}
#ifdef	debug
	_trace(" return(%d)",len);
#endif
return(len);
}

seek(des,off,how)
{
register struct file *f;
register int n;

top;
#ifdef	debug
	_trace("seek(%d,%o,%d)",des,off,how);
#endif
f = getf(des);
n = off;
switch(how)
	{
case 0:
	f->f_off[0]=0;
	f->f_off[1]=n;
	break;
case 3:
	f->f_off[0] = hmul(n,512);
	f->f_off[1] = n*512;
	break;
case 1:
	dpadd(f->f_off,n);
	break;
case 4:
	f->f_off[0] =+ n;
	break;
case 2:
	f->f_off[0] = hmul(f->f_last,512);
	f->f_off[1] = f->f_last*512;
	dpadd(f->f_off,n);
	break;
case 6:
	n =+ f->f_last;
	f->f_off[0] = hmul(n,512);
	f->f_off[1] = n*512;
	dpadd(f->f_off,n);
	break;
	}
return(des);
}
