Xinu7/src/serve11/sys/ttyread.c
/* ttyread.c - ttyread, readcopy */
#include <conf.h>
#include <kernel.h>
#include <tty.h>
#include <io.h>
/*------------------------------------------------------------------------
* ttyread - read one or more characters from a tty device
*------------------------------------------------------------------------
*/
ttyread(devptr, buff, count)
struct devsw *devptr;
int count;
char *buff;
{
char ps;
register struct tty *iptr;
int avail, nread;
char ch, eofch;
int donow, dolater;
if (count < 0)
return(SYSERR);
disable(ps);
if ( (avail=scount((iptr= &tty[devptr->dvminor])->isem)) < 0)
avail = 0;
if (count == 0) { /* read whatever is available */
if (avail == 0) {
restore(ps);
return(0);
}
count = avail;
}
if (count < avail) {
donow = count;
dolater = 0;
} else {
donow = avail;
dolater = count - avail;
}
nread = 0;
if (donow > 0) {
ch = iptr->ibuff[iptr->itail++];
if (iptr->itail >= IBUFLEN)
iptr->itail = 0;
if ( ((eofch=iptr->ieofc) == ch) && iptr->ieof) {
sreset(iptr->isem, avail-1);
restore(ps);
return(EOF);
}
*buff++ = ch;
for (nread=1 ; nread < donow ; ) {
ch = iptr->ibuff[iptr->itail];
if ( (ch==eofch) && iptr->ieof) {
sreset(iptr->isem, avail - nread);
restore(ps);
return(nread);
}
*buff++ = ch;
if (++iptr->itail >= IBUFLEN)
iptr->itail = 0;
nread++;
if (ch == NEWLINE || ch == RETURN) {
sreset(iptr->isem, avail - nread);
restore(ps);
return(nread);
}
}
sreset(iptr->isem, avail - nread);
}
donow = nread;
for (nread=0 ; nread < dolater ; ) {
wait(iptr->isem);
ch = iptr->ibuff[iptr->itail];
if (ch == iptr->ieofc && iptr->ieof) {
if (nread == 0 && donow == 0) {
if (++iptr->itail >= IBUFLEN)
iptr->itail = 0;
restore(ps);
return(EOF);
}
signal(iptr->isem);
break;
}
*buff++ = ch;
nread++;
if (++iptr->itail >= IBUFLEN)
iptr->itail = 0;
if (ch == NEWLINE || ch == RETURN)
break;
}
restore(ps);
return(donow + nread);
}