scsh-0.6/scsh/fdports1.c

128 lines
2.9 KiB
C

/* This file contains the code for doing the scsh file ports stuff.
** Copyright (c) 1993, 1994 by Olin Shivers.
**
** Note that this code mutates Scheme records -- it has the layout
** of fdports and their data records wired in. This is somewhat fragile.
*/
/* A note on the clearerr() calls herein: SunOS stdio input routines,
** contrary to POSIX, will return EOF if the stream's EOF flag is set,
** without trying to read the stream. This is a lose for tty's, which
** can frequently still be read from after the first EOF (e.g., if you
** type a ^D to bag out of a breakpoint, you would like the terminal
** input port to not shut down forever.)
**
** To fix this lossage, we are careful to call clearerr() before every
** input stream op.
*/
#include "sysdep.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "cstuff.h"
#define NUM_FDPORTS 256
#include "fdports.h"
/* Make sure our exports match up w/the implementation: */
#include "fdports1.h"
extern int errno;
static char const *fdes_modestr(int fd)
{
int flags = fcntl(fd,F_GETFL);
if( flags == -1 ) return NULL;
flags &= O_ACCMODE;
if( flags == O_WRONLY ) return "w";
else if( flags == O_RDONLY ) return "r";
else if( flags == O_RDWR ) return "r+";
fputs("That's impossible.\n", stderr);
abort();
_exit(-1);
/*NOTREACHED*/
}
/* The two following routines are for delimited read. */
s48_value read_delim(const char *delims, char *buf,
int fd, int start, int end,
int *nread)
{
char *cptr = buf+start, /* Location of last char deposited. */
*bufend = buf+end -1; /* Last writeable position. */
int retval;
char c;
while( 1 ) {
retval = read( fd, &c, 1 );
if( retval == 0 ) { /* Terminal case: EOF. */
*nread = cptr - buf - start;
return S48_EOF;
}
else if( retval == -1 ) { /* Terminal case: error. */
*nread = cptr - buf - start;
return s48_enter_fixnum(errno);
}
else if( delims[c] ) { /* Terminal case: delimiter char. */
*nread = cptr - buf - start;
return s48_enter_char(c);
}
else if( cptr == bufend ) { /* Terminal case: buffer overflow. */
*cptr = c;
*nread = end-start;
return S48_FALSE;
}
else if ( cptr > bufend ){
fputs("cptr > bufend.\n", stderr);
abort();
_exit(-1);
}
else {
*cptr++ = c;
}
}
}
s48_value skip_chars(const char *skipchars, int fd, int *nread)
{
int nr = 0; /* Number of skip chars read. */
char c;
while( 1 ) {
int retval = read ( fd, &c, 1 );
if( retval == 0 ) { /* Terminal case: EOF. */
*nread = nr;
return S48_FALSE;
}
if( retval == -1 ) { /* Terminal case: error. */
*nread = nr;
return s48_enter_fixnum(errno);
}
else if( !skipchars[c] ) { /* Terminal case: non-skip char. */
*nread = nr;
return s48_enter_char(c);
}
nr++;
}
}