128 lines
2.9 KiB
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++;
|
|
}
|
|
}
|