#include "rtunix.h"
/*		Copyright 1976 by Bill Webb. 		*/

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 == 03)
			{
			_gotattn();
			continue;
			}
		if ((r_jsw & LC_JSW) == 0 && l >= 'A' && l <= 'Z')
			l =- 'A'-'a';
		if(l == 032)
			break;
		if (l == '\\' && (r_jsw & LC_JSW) == 0)
			{
			l = ttyin();
			switch(l)
				{
			case '!':
				l = '|';
				break;
			case '(':
				l = '{';
				break;
			case ')':
				l = '}';
				break;
			case '^':
				l = '~';
				break;
			case '\'':
				l = '`';
				break;
			case '\\':
				break;
			default:
				if (l >= 'A' && l <= 'Z')
					break;
				buffer[len++] = '\\'; /* not special output backslash */
				break;
				}
			}
		buffer[len++] = l;
		if(l == '\n')
			break;
		}
	break;

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+off, 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 ((r_jsw & LC_JSW) == 0)
			{
			switch(l)
				{
			case '{':
				l = '(';
				break;
			case '}':
				l = ')';
				break;
			case '~':
				l = '^';
				break;
			case '|':
				l = '!';
				break;
			case '`':
				l = '\'';
				break;
			default:
				goto next;
				}
			ttyout('\\');
			}
	next:
		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);
		if (rtwrite(f->f_chan, blk++, _buff, 0400, 0) == -1)
			seterr(EIO);
		buffer =+ l;
		len =+ l;
		length =- l;
		dpadd(f->f_off,l);
		}
	if(length > 0)
		{
		if((l = length) & 1)
			++l;
		l =>> 1;
		if (rtwrite(f->f_chan, blk, buffer, l, 0) == -1)
			seterr(EIO);
		len =+ length;
		dpadd(f->f_off, length);
		blk =+ (length+511)/512;
		}
	if(++blk > f->f_length)
		f->f_length = 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] =+ hmul(n,512);
	dpadd(f->f_off,n*512);
	break;
case 2:
	f->f_off[0] = hmul(f->f_length,512);
	f->f_off[1] = f->f_length*512;
	dpadd(f->f_off,n);
	break;
case 6:
	n =+ f->f_length;
	f->f_off[0] = hmul(n,512);
	f->f_off[1] = n*512;
	break;
	}
return(des);
}

_move(len,s1,s2)
char *s1,*s2;
{
register int l;
register char *p1, *p2;
if(l = len)
	{
	p1 = s1;
	p2 = s2;
	do
		*p2++ = *p1++;
	while (--l);
	}
}
