1666 lines
41 KiB
C
1666 lines
41 KiB
C
/* Release 3.00 */
|
|||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* *
|
||
|
|
* cio2.c - common I/O *
|
||
|
|
* *
|
||
|
|
* COPYRIGHT (C) 1989 Jensen and Partners. All Rights Reserved *
|
||
|
|
* Written by Simon Knight. *
|
||
|
|
* *
|
||
|
|
* COPYRIGHT (C) 1991 Psion PLC. All Rights Reserved *
|
||
|
|
* Modified by NSM. *
|
||
|
|
* *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
#define _USE_TIME
|
||
|
|
#define _USE_CONIO
|
||
|
|
#include "clib.h"
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* buffer flushing functions. *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int _flsbuf(int ch, FILE *st) {
|
||
|
|
|
||
|
|
int flag;
|
||
|
|
|
||
|
|
ch&=0xFF;
|
||
|
|
flag=st->_flag;
|
||
|
|
if( (!flag) || (flag&_F_ERR))
|
||
|
|
return(-1);
|
||
|
|
if((flag&_F_EOF) && (flag&_F_IN)) {
|
||
|
|
lseek(st->_file, 0L, SEEK_END);
|
||
|
|
st->_flag|=_F_RST;
|
||
|
|
st->_flag&=(~(_F_IN|_F_EOF));
|
||
|
|
if(st->_size) {
|
||
|
|
_flusher(st);
|
||
|
|
--st->_cnt;
|
||
|
|
*st->_ptr++= (char) ch;
|
||
|
|
return(ch);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if((!(flag&_F_WRIT)) || (flag&_F_IN)
|
||
|
|
|| ((!(flag&_F_BIN)) && ((char) ch == EOF))) {
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
return(-1);
|
||
|
|
} /* return error */
|
||
|
|
if(st->_size) { /* buffered */
|
||
|
|
if(_flusher(st)== -1 ) /* flush buffer */
|
||
|
|
return(-1);
|
||
|
|
--st->_cnt; /* put overflow char in buffer */
|
||
|
|
*st->_ptr++= (char) ch;
|
||
|
|
return(ch);
|
||
|
|
}
|
||
|
|
st->_flag&=~_F_RST; /* clear reset flag */
|
||
|
|
if(flag&_F_APP)
|
||
|
|
lseek(st->_file, 0L, SEEK_END); /* unbuffered - write data */
|
||
|
|
}
|
||
|
|
st->_cnt=0; /* set buffer pointers */
|
||
|
|
st->_ptr=NULL;
|
||
|
|
st->_flag|=_F_OUT; /* set output flag */
|
||
|
|
if(_write(st->_file,&ch,1) != 1) {
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
if((ch == _CTLZ) && (!(flag&(_F_BIN|_F_DEV))))
|
||
|
|
/* ctl z - set EOF flag if */
|
||
|
|
st->_flag|=_F_EOF; /* text mode and not device */
|
||
|
|
return(ch);
|
||
|
|
}
|
||
|
|
|
||
|
|
int _flusher(FILE *st) /* empties output buffer */
|
||
|
|
|
||
|
|
{
|
||
|
|
unsigned wnum, flag;
|
||
|
|
char zbuf[128];
|
||
|
|
long pos;
|
||
|
|
int nr, sr;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if(flag&(_F_IN|_F_EOF))
|
||
|
|
return(-1);
|
||
|
|
if(flag&_F_RST) /* set up reset buffer for output */
|
||
|
|
{
|
||
|
|
st->_flag&=(~_F_RST);
|
||
|
|
st->_flag|=_F_OUT;
|
||
|
|
st->_cnt=st->_size;
|
||
|
|
st->_ptr=st->_base;
|
||
|
|
return(0); /* return - buffer wasn't full */
|
||
|
|
}
|
||
|
|
if(st->_cnt<0)
|
||
|
|
st->_cnt=0;
|
||
|
|
wnum=st->_size-st->_cnt;
|
||
|
|
if(wnum == 0) /* nothing to do - return */
|
||
|
|
return(0); /* buffer empty */
|
||
|
|
if(flag&_F_BIN) /* binary mode */
|
||
|
|
{
|
||
|
|
if(flag&_F_APP)
|
||
|
|
lseek(st->_file, 0L, SEEK_END); /* append */
|
||
|
|
if(_write(st->_file, st->_base, wnum) != wnum)
|
||
|
|
goto error;
|
||
|
|
}
|
||
|
|
else /* text mode */
|
||
|
|
{
|
||
|
|
if(flag&_F_APP) {
|
||
|
|
pos = lseek(st->_file, -128L, SEEK_END);
|
||
|
|
if(pos < 0)
|
||
|
|
lseek(st->_file, 0, SEEK_SET);
|
||
|
|
nr = _read(st->_file, zbuf, 128);
|
||
|
|
sr = nr;
|
||
|
|
if (nr == -1)
|
||
|
|
goto error;
|
||
|
|
while(--sr >= 0) {
|
||
|
|
if(zbuf[sr] != _CTLZ)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
pos = sr - nr + 1;
|
||
|
|
lseek(st->_file, pos, SEEK_END); /* append after last cltZ */
|
||
|
|
}
|
||
|
|
if(_write(st->_file, st->_base, wnum) == -1)
|
||
|
|
goto error;
|
||
|
|
if(st->_flag&_F_CTZ) {
|
||
|
|
st->_flag|=_F_EOF;
|
||
|
|
st->_cnt=0;
|
||
|
|
st->_ptr=st->_base;
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
st->_cnt=st->_size; /* set buffer pointers */
|
||
|
|
st->_ptr=st->_base;
|
||
|
|
st->_flag|=_F_OUT; /* set output flag */
|
||
|
|
return(0);
|
||
|
|
error:
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
st->_cnt=0;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* buffer filling functions *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int _filbuf(FILE *st)
|
||
|
|
{
|
||
|
|
int ch, n, flag;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!flag)||(flag&(_F_EOF|_F_ERR)))
|
||
|
|
return(-1);
|
||
|
|
if((flag&_F_OUT) || (!(flag&_F_READ)))
|
||
|
|
{
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
return(-1); /* return error */
|
||
|
|
}
|
||
|
|
if(st->_size) /* buffered */
|
||
|
|
{
|
||
|
|
if(_filler(st) <= 0 ) /* fill buffer */
|
||
|
|
return(-1);
|
||
|
|
--st->_cnt; /* get first char from buffer */
|
||
|
|
ch=*st->_ptr++;
|
||
|
|
return(ch&0xFF); /* return first character in buffer */
|
||
|
|
}
|
||
|
|
st->_cnt=0; /* reset pointers */
|
||
|
|
st->_flag|=_F_IN; /* set input flag */
|
||
|
|
st->_ptr=NULL;
|
||
|
|
st->_flag&=~_F_RST;
|
||
|
|
for(n=0; n<2; n++) /* unbuffered - read character */
|
||
|
|
{
|
||
|
|
if(_read(st->_file, &ch, 1) != 1)
|
||
|
|
{
|
||
|
|
st->_flag|=_F_EOF;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
ch&=0xFF;
|
||
|
|
if((flag&_F_BIN)||(ch != '\r')) /* dont translate if binary mode */
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if((!(flag&(_F_BIN|_F_DEV))) && (ch == _CTLZ))
|
||
|
|
st->_flag|=_F_EOF; /* ctl z end of file */
|
||
|
|
return(ch);
|
||
|
|
}
|
||
|
|
|
||
|
|
int _filler(FILE *st) /* fills buffer */
|
||
|
|
{
|
||
|
|
int flag, num;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if(flag&(_F_OUT|_F_EOF))
|
||
|
|
return(-1);
|
||
|
|
if(flag&_F_RST)
|
||
|
|
st->_flag&=~_F_RST;
|
||
|
|
num =_read(st->_file, st->_base, st->_size);
|
||
|
|
st->_ptr=st->_base;
|
||
|
|
if(( num == -1) && (num != st->_size))
|
||
|
|
goto error;
|
||
|
|
st->_cnt=num; /* reset pointers */
|
||
|
|
st->_flag|=_F_IN; /* set input flag */
|
||
|
|
if(num == 0)
|
||
|
|
{
|
||
|
|
st->_flag|=_F_EOF; /* end of file */
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
return(num);
|
||
|
|
error: /* read error */
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
st->_cnt=0;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
int fputchar(int ch)
|
||
|
|
{
|
||
|
|
return(fputc(ch, stdout));
|
||
|
|
}
|
||
|
|
|
||
|
|
int fgetchar()
|
||
|
|
{
|
||
|
|
return(fgetc(stdin));
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* ungetc - put character back onto input stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int ungetc(int ch, FILE *st)
|
||
|
|
{
|
||
|
|
int flag;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!flag) || (flag&_F_ERR))
|
||
|
|
return(EOF);
|
||
|
|
if(ch == EOF)
|
||
|
|
return(EOF); /* return EOF if error, EOF or not read mode */
|
||
|
|
if(flag&_F_OUT)
|
||
|
|
{
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
return(EOF); /* return EOF if error, EOF or not read mode */
|
||
|
|
}
|
||
|
|
ch&=0xFF;
|
||
|
|
st->_flag&=(~_F_EOF); /* clear EOF */
|
||
|
|
if((flag&_F_RST) || (st->_size == 0))
|
||
|
|
{
|
||
|
|
st->_flag&=(~_F_RST);
|
||
|
|
st->_flag|=_F_IN;
|
||
|
|
if(st->_size)
|
||
|
|
st->_ptr=st->_base;
|
||
|
|
else
|
||
|
|
st->_ptr= (char *) &st->_pback;
|
||
|
|
if((ch == 0xA) && (!(st->_flag&_F_BIN))) {
|
||
|
|
st->_cnt=2;
|
||
|
|
*((unsigned *)st->_ptr)=0xA0D;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
st->_cnt=1;
|
||
|
|
*st->_ptr=ch;
|
||
|
|
}
|
||
|
|
return(ch);
|
||
|
|
}
|
||
|
|
if((ch == 0xA) && (!(st->_flag&_F_BIN)) && (st->_cnt < st->_size-2)) {
|
||
|
|
*--st->_ptr= (char) 0xD;
|
||
|
|
st->_cnt++;
|
||
|
|
}
|
||
|
|
*--st->_ptr= (char) ch; /* buffer not full - put it in buffer */
|
||
|
|
st->_cnt++;
|
||
|
|
return(ch);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* rewind - rewind and clear error flag *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
void rewind(FILE *st)
|
||
|
|
{
|
||
|
|
if(st->_flag)
|
||
|
|
{
|
||
|
|
st->_flag&=(~_F_ERR);
|
||
|
|
fseek(st, 0L, SEEK_SET);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* flushall - flush all open streams *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int flushall()
|
||
|
|
{
|
||
|
|
int n, count;
|
||
|
|
|
||
|
|
count=0;
|
||
|
|
for(n=0; n< _open_max; n++)
|
||
|
|
{
|
||
|
|
if(_iob[n]._flag) /* inc count if open file */
|
||
|
|
{
|
||
|
|
fflush(&_iob[n]); /* flush buffer */
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return(count); /* return number of open streams */
|
||
|
|
}
|
||
|
|
|
||
|
|
void _flushall()
|
||
|
|
{
|
||
|
|
int n;
|
||
|
|
|
||
|
|
for(n=0; n<_open_max; n++)
|
||
|
|
{
|
||
|
|
if((_iob[n]._flag) && (_iob[n]._size))
|
||
|
|
_flusher(&_iob[n]); /* flush buffer */
|
||
|
|
}
|
||
|
|
return; /* return number of open streams */
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fopen - open stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
#define _WRITE 2
|
||
|
|
#define NODEFMODE 4
|
||
|
|
#define _READ 8
|
||
|
|
|
||
|
|
FILE *fopen(const char *path, const char *type)
|
||
|
|
{
|
||
|
|
int num;
|
||
|
|
int handle, flag, mode;
|
||
|
|
|
||
|
|
flag=_F_RST;
|
||
|
|
mode=0;
|
||
|
|
if(_scan_type(type, &flag, &mode) < 0) /* get access mode */
|
||
|
|
return(NULL);
|
||
|
|
handle=_open_stream(path, &flag, mode); /* open the file */
|
||
|
|
if(handle < 0)
|
||
|
|
return(NULL);
|
||
|
|
num=_free_stream(); /* find a free stream */
|
||
|
|
if(num < 0)
|
||
|
|
{
|
||
|
|
close(handle);
|
||
|
|
return(NULL);
|
||
|
|
}
|
||
|
|
return(_alloc_stream(&_iob[num], handle, flag));
|
||
|
|
} /* allocate the stream */
|
||
|
|
|
||
|
|
int _scan_type(const char *type, int *fptr, int *mptr)
|
||
|
|
{ /* evaluate file mode */
|
||
|
|
int c, n;
|
||
|
|
|
||
|
|
switch(type[0])
|
||
|
|
{
|
||
|
|
case 'r':
|
||
|
|
*mptr|=(_READ|O_EXCL);
|
||
|
|
break;
|
||
|
|
case 'w':
|
||
|
|
*mptr|=(O_TRUNC|O_CREAT|_WRITE);
|
||
|
|
break;
|
||
|
|
case 'a':
|
||
|
|
*fptr|=_F_APP;
|
||
|
|
*mptr|=(_WRITE|O_APPEND|O_CREAT);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
n=0;
|
||
|
|
do
|
||
|
|
{
|
||
|
|
c=type[++n];
|
||
|
|
switch(c)
|
||
|
|
{
|
||
|
|
case'+':
|
||
|
|
*mptr|=(_READ|_WRITE);
|
||
|
|
break;
|
||
|
|
case'b':
|
||
|
|
*fptr|=_F_BIN;
|
||
|
|
*mptr|=NODEFMODE|O_BINARY;
|
||
|
|
break;
|
||
|
|
case't':
|
||
|
|
*mptr|=NODEFMODE|O_TEXT;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} while((n < 3) && (c));
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
int _open_stream(const char *path, int *fptr, int mode)
|
||
|
|
{
|
||
|
|
unsigned access, permission;
|
||
|
|
|
||
|
|
access=0; /* translates level 2 */
|
||
|
|
permission=0; /* access and permission */
|
||
|
|
if(!(mode&NODEFMODE)) /* flags to level 1 and */
|
||
|
|
{ /* uses open to get handle */
|
||
|
|
if(_fmode==O_BINARY)
|
||
|
|
{
|
||
|
|
*fptr|=_F_BIN;
|
||
|
|
access= O_BINARY;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
access=O_TEXT;
|
||
|
|
}
|
||
|
|
if(mode&_WRITE)
|
||
|
|
{
|
||
|
|
permission|=S_IWRITE;
|
||
|
|
if(mode&_READ)
|
||
|
|
{
|
||
|
|
*fptr|=_F_RDWR;
|
||
|
|
permission|=S_IREAD;
|
||
|
|
access|=O_RDWR;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
*fptr|=_F_WRIT;
|
||
|
|
access|=O_WRONLY;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
access|=O_RDONLY;
|
||
|
|
permission=S_IREAD;
|
||
|
|
*fptr|=_F_READ;
|
||
|
|
}
|
||
|
|
access|= (mode&(O_TEXT|O_BINARY|O_CREAT|O_TRUNC|O_EXCL|O_APPEND));
|
||
|
|
return(open(path, access, permission));
|
||
|
|
}
|
||
|
|
|
||
|
|
int _valid_stream(FILE *st) /* checks stream pointer is valid */
|
||
|
|
{
|
||
|
|
if((st > &_iob[_open_max-1]) || (st < _iob) || (st->_flag==0) )
|
||
|
|
return(FALSE);
|
||
|
|
return(TRUE);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fgetpos - get current stream position *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int fgetpos(FILE *st, fpos_t *fp)
|
||
|
|
{
|
||
|
|
long pos;
|
||
|
|
|
||
|
|
pos=ftell(st);
|
||
|
|
if(pos == -1)
|
||
|
|
return(-1);
|
||
|
|
*fp= (fpos_t) pos;
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fsetpos - set current stream position *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int fsetpos(FILE *st, const fpos_t *fp)
|
||
|
|
{
|
||
|
|
return fseek(st, *fp, SEEK_SET);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* close.c - level 1 I/O - close file. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
int close(int handle)
|
||
|
|
{
|
||
|
|
int n;
|
||
|
|
|
||
|
|
n=_close(handle); /* close file */
|
||
|
|
if(n < 0)
|
||
|
|
return(-1); /* return -1 if error */
|
||
|
|
_openfd[handle]=0; /* zero file descriptor */
|
||
|
|
return(0); /* success - return 0 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* eof.c - level 1 I/O - test for eof. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
int eof(int handle)
|
||
|
|
{
|
||
|
|
if( (_openfd[handle]&O_TEXT) && (_openfd[handle]&_O_EOF))
|
||
|
|
return(1); /* text file ctl z eof */
|
||
|
|
if(_openfd[handle]&O_DEVICE)
|
||
|
|
return(0); /* device - no eof unless text mode */
|
||
|
|
return(_eof(handle));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* umask.c - level 1 I/O - set file permission mask. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
unsigned umask(unsigned permission)
|
||
|
|
{
|
||
|
|
unsigned ret;
|
||
|
|
|
||
|
|
ret=_fmask;
|
||
|
|
_fmask=permission;
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* filelength.c - returns file length. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
long filelength(int handle)
|
||
|
|
{
|
||
|
|
long pos, size;
|
||
|
|
|
||
|
|
pos=tell(handle); /* save file position */
|
||
|
|
if(pos == -1)
|
||
|
|
return(pos);
|
||
|
|
size=lseek(handle, 0L, SEEK_END); /* get file length */
|
||
|
|
lseek(handle, pos, SEEK_SET); /* restore original file position */
|
||
|
|
return(size);
|
||
|
|
}
|
||
|
|
|
||
|
|
int rmtmp(void)
|
||
|
|
{
|
||
|
|
int n, files;
|
||
|
|
|
||
|
|
n=0;
|
||
|
|
files=0;
|
||
|
|
while(n < _open_max)
|
||
|
|
{
|
||
|
|
if (_tmpfiles[n])
|
||
|
|
{
|
||
|
|
fclose(_tmpfptrs[n]);
|
||
|
|
unlink(_tmpfiles[n]);
|
||
|
|
_tmpfiles[n]=NULL;
|
||
|
|
++files;
|
||
|
|
}
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
_exit_tmp=NULL;
|
||
|
|
return(files);
|
||
|
|
}
|
||
|
|
|
||
|
|
FILE *tmpfile(void)
|
||
|
|
{
|
||
|
|
int handle,i;
|
||
|
|
FILE *ret;
|
||
|
|
char *e,*p,name[0x128];
|
||
|
|
|
||
|
|
name[0]=0;
|
||
|
|
if ((e=getenv("TMP"))!=NULL && (i=strlen(e))!=0)
|
||
|
|
{
|
||
|
|
strcpy(&name[0],e);
|
||
|
|
p=(&name[i-1]);
|
||
|
|
if (*p!='\\')
|
||
|
|
{
|
||
|
|
*p++='\\';
|
||
|
|
*p=0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if ((handle=_creat_temp(&name[0],FA_NORMAL))==(-1))
|
||
|
|
return(NULL);
|
||
|
|
_openfd[handle]=O_BINARY|O_RDWR;
|
||
|
|
i=strlen(&name[0])+1;
|
||
|
|
if ((p=malloc(i))==NULL)
|
||
|
|
goto failed1;
|
||
|
|
strcpy(p,&name[0]);
|
||
|
|
_tmpfiles[handle]=p;
|
||
|
|
if ((ret=fdopen(handle,"w+b"))==NULL)
|
||
|
|
goto failed2;
|
||
|
|
_tmpfptrs[handle]=ret;
|
||
|
|
_exit_tmp=_exit2;
|
||
|
|
return(ret);
|
||
|
|
failed2:
|
||
|
|
free(_tmpfiles[handle]);
|
||
|
|
_tmpfiles[handle]=NULL;
|
||
|
|
failed1:
|
||
|
|
_openfd[handle]=0;
|
||
|
|
_close(handle);
|
||
|
|
return(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* console I/O section. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
char *cgets(char *s)
|
||
|
|
{
|
||
|
|
extern void *winHandle;
|
||
|
|
extern void p_xwind(void);
|
||
|
|
|
||
|
|
if(!_p_init)
|
||
|
|
{
|
||
|
|
_i_putch=_d_putch;
|
||
|
|
_i_cgets=_d_cgets;
|
||
|
|
_p_init=-1;
|
||
|
|
if (winHandle==NULL)
|
||
|
|
p_xwind();
|
||
|
|
}
|
||
|
|
return(_i_cgets(s));
|
||
|
|
}
|
||
|
|
|
||
|
|
int sopen(const char *path, int access, int shflag, ...)
|
||
|
|
{
|
||
|
|
va_list _v_argptr;
|
||
|
|
|
||
|
|
va_start(_v_argptr, shflag);
|
||
|
|
return(open(path, access|shflag, va_arg(_v_argptr, int)));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* macro equivalents. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
int ferror(FILE *st)
|
||
|
|
{
|
||
|
|
return((st)->_flag & _F_ERR);
|
||
|
|
}
|
||
|
|
|
||
|
|
int feof(FILE *st)
|
||
|
|
{
|
||
|
|
return((st)->_flag & _F_EOF);
|
||
|
|
}
|
||
|
|
|
||
|
|
int fileno(FILE *st)
|
||
|
|
{
|
||
|
|
return((st)->_file);
|
||
|
|
}
|
||
|
|
|
||
|
|
int remove(const char *path)
|
||
|
|
{
|
||
|
|
return(unlink(path));
|
||
|
|
}
|
||
|
|
|
||
|
|
int getc(FILE *st)
|
||
|
|
{
|
||
|
|
return(fgetc(st));
|
||
|
|
}
|
||
|
|
|
||
|
|
int putc(int c, FILE *st)
|
||
|
|
{
|
||
|
|
return(fputc(c, st));
|
||
|
|
}
|
||
|
|
|
||
|
|
int getchar()
|
||
|
|
{
|
||
|
|
return(fgetc(stdin));
|
||
|
|
}
|
||
|
|
|
||
|
|
int putchar(int c)
|
||
|
|
{
|
||
|
|
return(fputc(c, stdout));
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* puts - send string to stdout *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int puts(const char *s)
|
||
|
|
{
|
||
|
|
int n, c, ret;
|
||
|
|
|
||
|
|
n=0;
|
||
|
|
while((c=s[n++]) != 0)
|
||
|
|
{
|
||
|
|
if(putchar(c) == EOF)
|
||
|
|
{
|
||
|
|
ret=-1;
|
||
|
|
goto puts_error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(putchar('\n') == EOF)
|
||
|
|
{
|
||
|
|
ret=-1;
|
||
|
|
goto puts_error;
|
||
|
|
}
|
||
|
|
ret=fflush(stdout);
|
||
|
|
puts_error:
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* gets - get string from stdin *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
char *gets(char *s)
|
||
|
|
{
|
||
|
|
int n, c;
|
||
|
|
char *ret;
|
||
|
|
|
||
|
|
n=0;
|
||
|
|
while((c=getchar()) != '\n')
|
||
|
|
{
|
||
|
|
if(c < 0)
|
||
|
|
{
|
||
|
|
if((feof(stdin)) && (n))
|
||
|
|
break;
|
||
|
|
ret=NULL;
|
||
|
|
goto gets_error;
|
||
|
|
}
|
||
|
|
s[n++]= (char) c;
|
||
|
|
}
|
||
|
|
s[n]=0;
|
||
|
|
ret=s;
|
||
|
|
gets_error:
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fputs - put string on stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int fputs(const char *s, FILE *st)
|
||
|
|
{
|
||
|
|
int n, c, ret;
|
||
|
|
|
||
|
|
ret=0;
|
||
|
|
n=0;
|
||
|
|
while((c=s[n++]) != 0)
|
||
|
|
{
|
||
|
|
if(fputc(c, st) == EOF )
|
||
|
|
{
|
||
|
|
ret=-1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(st->_flag&_F_DEV)
|
||
|
|
fflush(st);
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fgets - get string from stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
char *fgets(char *s, int num, FILE *st)
|
||
|
|
{
|
||
|
|
int n, c;
|
||
|
|
char *ret;
|
||
|
|
|
||
|
|
n=0;
|
||
|
|
ret=s;
|
||
|
|
while( n < num-1)
|
||
|
|
{
|
||
|
|
c=fgetc(st);
|
||
|
|
if(c == -1)
|
||
|
|
{
|
||
|
|
if((feof(st)) && (n))
|
||
|
|
break;
|
||
|
|
ret=NULL;
|
||
|
|
goto fgets_end;
|
||
|
|
}
|
||
|
|
s[n++]= (char) c;
|
||
|
|
if(c == '\n')
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
s[n]=0;
|
||
|
|
fgets_end:
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* getw - get word from stream *
|
||
|
|
* putw - put word on stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int getw(FILE *st)
|
||
|
|
{
|
||
|
|
unsigned hibyte, lobyte;
|
||
|
|
|
||
|
|
lobyte=fgetc(st);
|
||
|
|
hibyte=fgetc(st);
|
||
|
|
return( (hibyte*0x100)+lobyte);
|
||
|
|
}
|
||
|
|
|
||
|
|
int putw(int num, FILE *st)
|
||
|
|
{
|
||
|
|
int ret;
|
||
|
|
|
||
|
|
fputc(num&0xFF, st);
|
||
|
|
ret=fputc((num&0xFF00)>>8, st);
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* clearerr - clear error and EOF flags and reset buffer status *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
void clearerr(FILE *st)
|
||
|
|
|
||
|
|
{
|
||
|
|
if(st->_flag)
|
||
|
|
{
|
||
|
|
st->_flag&=~(_F_ERR|_F_EOF|_F_CTZ);
|
||
|
|
_openfd[st->_file]&= (~_O_EOF);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fseek - position stream pointer *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int fseek(FILE *st, long offset, int orig)
|
||
|
|
{
|
||
|
|
long ret, temp, pos;
|
||
|
|
int flag;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!flag) || (flag&_F_ERR))
|
||
|
|
{
|
||
|
|
errno=EBADF;
|
||
|
|
ret=-1;
|
||
|
|
goto fseek_end;
|
||
|
|
}
|
||
|
|
if(orig == SEEK_CUR)
|
||
|
|
{
|
||
|
|
if((!(flag&(_F_WRIT|_F_RST))) && (st->_size)) {
|
||
|
|
if(offset == 0) {
|
||
|
|
ret=0;
|
||
|
|
goto fseek_end;
|
||
|
|
}
|
||
|
|
else if(offset < 0)
|
||
|
|
pos=st->_ptr-st->_base;
|
||
|
|
else
|
||
|
|
pos=st->_cnt;
|
||
|
|
if(pos > labs(offset)) {
|
||
|
|
st->_cnt-=(short)offset;
|
||
|
|
st->_ptr+=(short)offset;
|
||
|
|
ret=0;
|
||
|
|
goto fseek_end;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
temp=ftell(st);
|
||
|
|
ret=fseek(st, temp+offset, SEEK_SET);
|
||
|
|
if(ret)
|
||
|
|
ret = -1L;
|
||
|
|
goto fseek_end;
|
||
|
|
}
|
||
|
|
if((st->_size) && (flag&_F_OUT)) /* flush output buffer */
|
||
|
|
_flusher(st);
|
||
|
|
st->_pback=0; /* reset buffer */
|
||
|
|
st->_cnt=0;
|
||
|
|
st->_flag|=_F_RST;
|
||
|
|
ret=lseek(st->_file, offset, orig);
|
||
|
|
st->_flag&=~(_F_IN|_F_OUT|_F_EOF|_F_CTZ); /* clear direction flag and EOF */
|
||
|
|
_openfd[st->_file]&=~(_O_EOF);
|
||
|
|
fseek_end:
|
||
|
|
if(ret < 0)
|
||
|
|
return(1);
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* ftell - return stream pointer *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
long ftell(FILE *st)
|
||
|
|
{
|
||
|
|
long pos, ret;
|
||
|
|
int flag;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!flag) || (flag&_F_ERR))
|
||
|
|
{
|
||
|
|
errno=EINVAL;
|
||
|
|
ret=-1L;
|
||
|
|
goto ftell_error;
|
||
|
|
}
|
||
|
|
if((flag&_F_RST) || (!st->_size)) /* unbuffered or reset stream */
|
||
|
|
{
|
||
|
|
st->_cnt=0;
|
||
|
|
ret=tell(st->_file);
|
||
|
|
}
|
||
|
|
else if(flag&_F_OUT) /* output stream */
|
||
|
|
{
|
||
|
|
_flusher(st); /* flush stream */
|
||
|
|
ret=tell(st->_file);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
pos=tell(st->_file); /* input stream */
|
||
|
|
if(st->_pback != 0)
|
||
|
|
--pos;
|
||
|
|
if((flag&_F_BIN) && (st->_pback == 0xA0D))
|
||
|
|
--pos;
|
||
|
|
ret=pos-st->_cnt;
|
||
|
|
}
|
||
|
|
ftell_error:
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fflush - flush stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int fflush(FILE *st)
|
||
|
|
{
|
||
|
|
int flag, ret;
|
||
|
|
|
||
|
|
if(st == NULL)
|
||
|
|
{
|
||
|
|
flushall();
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!flag)||(flag&(_F_EOF|_F_ERR)))
|
||
|
|
{
|
||
|
|
ret=EOF; /* error EOF or not open */
|
||
|
|
goto fflush_end;
|
||
|
|
}
|
||
|
|
if(!st->_size)
|
||
|
|
{
|
||
|
|
st->_cnt=0;
|
||
|
|
st->_flag|=_F_RST;
|
||
|
|
st->_flag&=~(_F_OUT|_F_IN);
|
||
|
|
ret=0; /* no buffer */
|
||
|
|
goto fflush_end;
|
||
|
|
}
|
||
|
|
if(flag&_F_OUT)
|
||
|
|
ret=_flusher(st); /* flush output buffer */
|
||
|
|
else
|
||
|
|
{
|
||
|
|
fseek(st, ftell(st), SEEK_SET);
|
||
|
|
ret=0;
|
||
|
|
goto fflush_end;
|
||
|
|
}
|
||
|
|
st->_pback=0; /* reset buffer */
|
||
|
|
st->_cnt=0;
|
||
|
|
st->_flag|=_F_RST;
|
||
|
|
st->_flag&=~(_F_OUT|_F_IN);
|
||
|
|
fflush_end:
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fdopen - assign stream to handle *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
#define _WRITE 2
|
||
|
|
#define NODEFMODE 4
|
||
|
|
#define _READ 8
|
||
|
|
|
||
|
|
FILE *fdopen(int handle, char *type)
|
||
|
|
{
|
||
|
|
int num;
|
||
|
|
int flag, mode;
|
||
|
|
|
||
|
|
flag=_F_RST;
|
||
|
|
mode=0;
|
||
|
|
if(handle < 0) /* bad handle */
|
||
|
|
{
|
||
|
|
errno=EBADF;
|
||
|
|
return(NULL);
|
||
|
|
}
|
||
|
|
if(_scan_type(type, &flag, &mode) < 0) /* get the access mode */
|
||
|
|
return(NULL);
|
||
|
|
if((!(mode&NODEFMODE))&&(_fmode==O_BINARY))
|
||
|
|
flag|=_F_BIN;
|
||
|
|
if(mode&_WRITE)
|
||
|
|
{
|
||
|
|
if(mode&_READ)
|
||
|
|
flag|=_F_RDWR;
|
||
|
|
else
|
||
|
|
flag|=_F_WRIT;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
flag|=_F_READ;
|
||
|
|
num=_free_stream(); /* find a free stream */
|
||
|
|
if(num < 0)
|
||
|
|
{
|
||
|
|
close(handle);
|
||
|
|
return(NULL);
|
||
|
|
}
|
||
|
|
return(_alloc_stream(&_iob[num], handle, flag));
|
||
|
|
} /* allocate the stream */
|
||
|
|
|
||
|
|
FILE * _alloc_stream(FILE *stream, int handle, int flag)
|
||
|
|
{
|
||
|
|
stream->_file=handle; /* allocates buffer and sets flags */
|
||
|
|
stream->_flag=flag;
|
||
|
|
stream->_cnt=0;
|
||
|
|
stream->_pback=0;
|
||
|
|
stream->_size=BUFSIZ;
|
||
|
|
if(_openfd[handle]&O_DEVICE)
|
||
|
|
stream->_flag|=_F_DEV;
|
||
|
|
if((stream->_base= (char *) malloc(BUFSIZ)) == NULL)
|
||
|
|
{
|
||
|
|
stream->_size=0; /* no memory for buffer */
|
||
|
|
stream->_ptr=NULL;
|
||
|
|
errno=ENOMEM;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
stream->_size=BUFSIZ;
|
||
|
|
stream->_ptr=stream->_base;
|
||
|
|
}
|
||
|
|
return(stream);
|
||
|
|
}
|
||
|
|
|
||
|
|
int _free_stream() /* find a free stream */
|
||
|
|
{
|
||
|
|
int n;
|
||
|
|
|
||
|
|
for(n=0; n < _open_max; n++)
|
||
|
|
{
|
||
|
|
if(_iob[n]._flag == 0)
|
||
|
|
return(n);
|
||
|
|
}
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* freopen - close existing stream and assign new file *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
FILE *freopen(const char *path, const char *type, FILE *st)
|
||
|
|
{
|
||
|
|
int handle, flag, mode;
|
||
|
|
|
||
|
|
if(fclose(st) == EOF) /* close old stream */
|
||
|
|
return(NULL);
|
||
|
|
flag=_F_RST;
|
||
|
|
mode=0;
|
||
|
|
if(_scan_type(type, &flag, &mode) < 0) /* get file mode */
|
||
|
|
goto fr_error;
|
||
|
|
handle=_open_stream(path, &flag, mode); /* open new */
|
||
|
|
if(handle < 0)
|
||
|
|
goto fr_error;
|
||
|
|
return(_alloc_stream(st, handle, flag)); /* assign to stream */
|
||
|
|
fr_error:
|
||
|
|
return(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fclose - close stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int fclose(FILE *st)
|
||
|
|
{
|
||
|
|
int ret;
|
||
|
|
|
||
|
|
ret=0;
|
||
|
|
if(!_valid_stream(st))
|
||
|
|
{
|
||
|
|
ret=-1;
|
||
|
|
goto fclose_error;
|
||
|
|
}
|
||
|
|
if(st->_size)
|
||
|
|
_flusher(st); /* flush buffer if any */
|
||
|
|
if(close(st->_file) < 0) /* close file */
|
||
|
|
ret=-1;
|
||
|
|
if((st->_base != NULL) && (!(st->_flag&_F_UBUF)))
|
||
|
|
free(st->_base); /* free system allocated buffer */
|
||
|
|
st->_flag=0; /* free stream */
|
||
|
|
if(_tmpfiles[st->_file])
|
||
|
|
{
|
||
|
|
unlink(_tmpfiles[st->_file]);
|
||
|
|
free(_tmpfiles[st->_file]);
|
||
|
|
_tmpfiles[st->_file]=NULL;
|
||
|
|
}
|
||
|
|
fclose_error:
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fcloseall - closes all streams except standards *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int fcloseall(void)
|
||
|
|
{
|
||
|
|
int n, count;
|
||
|
|
|
||
|
|
count=0;
|
||
|
|
for(n=3; n < _open_max; n++)
|
||
|
|
{
|
||
|
|
if(fclose(&_iob[n]) == 0)
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
return(count);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* setbuf - allocates user buffer to stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
void setbuf(FILE *st, char *buffer)
|
||
|
|
{
|
||
|
|
if((!_valid_stream(st))||(!(st->_flag&_F_RST))||(st->_flag&_F_UBUF))
|
||
|
|
return;
|
||
|
|
if(st->_base != NULL) /* free any system buffer */
|
||
|
|
free(st->_base);
|
||
|
|
st->_base=buffer; /* use user buffer */
|
||
|
|
st->_ptr=buffer;
|
||
|
|
if(buffer != NULL)
|
||
|
|
{
|
||
|
|
st->_size=BUFSIZ;
|
||
|
|
st->_flag|=_F_UBUF;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
st->_size=0;
|
||
|
|
st->_flag&=~_F_LBUF;
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* setvbuf - allocates user or system buffer to stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
int setvbuf(FILE *st, char *buffer, int type, size_t size)
|
||
|
|
{
|
||
|
|
int flag;
|
||
|
|
|
||
|
|
if((type < _IOFBF) || (type > _IONBF) || ((int) size < 0))
|
||
|
|
return(1);
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!_valid_stream(st))||(!(flag&_F_RST))||(size < 0))
|
||
|
|
{
|
||
|
|
return(1);
|
||
|
|
}
|
||
|
|
if((st->_base != NULL) || (!(st->_flag&_F_UBUF))) /* free old buffer */
|
||
|
|
free(st->_base);
|
||
|
|
st->_flag&=(~_F_LBUF|_F_IN|_F_OUT);
|
||
|
|
if(type != _IONBF)
|
||
|
|
{
|
||
|
|
if(buffer==NULL)
|
||
|
|
{ /* allocate new system buffer */
|
||
|
|
buffer=malloc(size);
|
||
|
|
if(buffer==NULL)
|
||
|
|
{
|
||
|
|
errno=ENOMEM;
|
||
|
|
return(1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else /* user buffer */
|
||
|
|
st->_flag|=_F_UBUF;
|
||
|
|
st->_base=buffer;
|
||
|
|
st->_ptr=buffer;
|
||
|
|
st->_size=size;
|
||
|
|
if(type == _IOLBF) /* line buffered */
|
||
|
|
st->_flag|=_F_LBUF;
|
||
|
|
}
|
||
|
|
else /* no buffer */
|
||
|
|
{
|
||
|
|
st->_size=0;
|
||
|
|
st->_base=NULL;
|
||
|
|
st->_ptr=NULL;
|
||
|
|
st->_cnt=0;
|
||
|
|
}
|
||
|
|
setvbuf_error:
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fread - get a number of data blocks from stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
size_t fread(void *buf, size_t size, size_t count, FILE *st)
|
||
|
|
{
|
||
|
|
unsigned numtoread;
|
||
|
|
unsigned pos;
|
||
|
|
int flag;
|
||
|
|
char *buffer;
|
||
|
|
long total, numleft, p;
|
||
|
|
size_t ret;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!flag) || (size == 0) || (count==0) || (flag&(_F_ERR|_F_EOF)))
|
||
|
|
{
|
||
|
|
ret=0;
|
||
|
|
goto fread_error;
|
||
|
|
}
|
||
|
|
if((flag&_F_OUT) || (!(st->_flag&_F_READ)))
|
||
|
|
{
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
ret=0;
|
||
|
|
goto fread_error;
|
||
|
|
}
|
||
|
|
st->_flag|=_F_IN;
|
||
|
|
buffer=(char *)buf;
|
||
|
|
total=size*count; /* how many bytes are there to read */
|
||
|
|
pos=0;
|
||
|
|
if((st->_size == 0) || (!(st->_flag&_F_BIN)))
|
||
|
|
{
|
||
|
|
for(p=0; p < total; p++) /* unbuffered */
|
||
|
|
{
|
||
|
|
ret=getc(st);
|
||
|
|
if(ret == EOF )
|
||
|
|
break;
|
||
|
|
buffer[pos]= (char) ret;
|
||
|
|
pos++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
numleft=total;
|
||
|
|
p=0;
|
||
|
|
do
|
||
|
|
{
|
||
|
|
if(st->_cnt == 0) /* fill empty buffer */
|
||
|
|
{
|
||
|
|
if(_filler(st) <= 0)
|
||
|
|
break; /* error or EOF */
|
||
|
|
}
|
||
|
|
if( (long) (unsigned) st->_cnt >= numleft) /* read entire item */
|
||
|
|
numtoread = (unsigned) numleft;
|
||
|
|
else
|
||
|
|
numtoread=st->_cnt; /* read entire buffer */
|
||
|
|
memcpy(buffer, st->_ptr, numtoread);
|
||
|
|
st->_cnt-=numtoread;
|
||
|
|
buffer+=numtoread;
|
||
|
|
st->_ptr+=numtoread;
|
||
|
|
numleft-=numtoread;
|
||
|
|
p+=numtoread;
|
||
|
|
}while(numleft);
|
||
|
|
}
|
||
|
|
ret=(int) p/size;
|
||
|
|
fread_error:
|
||
|
|
return(ret); /* return number of complete items read */
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************************************************
|
||
|
|
* fwrite - put a number of data blocks on stream *
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
size_t fwrite(const void *buf, size_t size, size_t count, FILE *st)
|
||
|
|
{
|
||
|
|
unsigned numtowrite;
|
||
|
|
unsigned pos;
|
||
|
|
char *buffer;
|
||
|
|
long total, numleft, p;
|
||
|
|
int flag;
|
||
|
|
size_t ret;
|
||
|
|
|
||
|
|
flag=st->_flag;
|
||
|
|
if((!flag) || (size == 0) || (count==0) || (flag&(_F_ERR|_F_EOF)))
|
||
|
|
{
|
||
|
|
ret=0;
|
||
|
|
goto fwrite_error;
|
||
|
|
}
|
||
|
|
if((flag&_F_IN) || (!(st->_flag&_F_WRIT)))
|
||
|
|
{
|
||
|
|
st->_flag|=_F_ERR;
|
||
|
|
ret=0;
|
||
|
|
goto fwrite_error;
|
||
|
|
}
|
||
|
|
st->_flag|=_F_OUT;
|
||
|
|
buffer=(char *)buf;
|
||
|
|
pos=0;
|
||
|
|
total=size*count;
|
||
|
|
if((st->_size == 0) || (!(st->_flag&_F_BIN)))
|
||
|
|
{
|
||
|
|
for(p=0; p < total; p++) /* unbuffered */
|
||
|
|
{
|
||
|
|
if(putc(buffer[pos], st) == -1)
|
||
|
|
break;
|
||
|
|
pos++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
numleft=total;
|
||
|
|
p=0;
|
||
|
|
do
|
||
|
|
{
|
||
|
|
if( (long) (unsigned) st->_cnt >= numleft) /* write entire item */
|
||
|
|
numtowrite= (unsigned) numleft;
|
||
|
|
else
|
||
|
|
numtowrite=st->_cnt; /* write entire buffer */
|
||
|
|
memcpy(st->_ptr, buffer, numtowrite);
|
||
|
|
st->_cnt-=numtowrite;
|
||
|
|
buffer+=numtowrite;
|
||
|
|
st->_ptr+=numtowrite;
|
||
|
|
numleft-= (long) numtowrite;
|
||
|
|
if(st->_cnt == 0)
|
||
|
|
{
|
||
|
|
if(_flusher(st) < 0)
|
||
|
|
break; /* error */
|
||
|
|
}
|
||
|
|
p+=numtowrite;
|
||
|
|
}while(numleft);
|
||
|
|
}
|
||
|
|
ret=(int) p/size;
|
||
|
|
fwrite_error:
|
||
|
|
return(ret); /* return number of complete items written */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*--------------------------------------------------------------------------*
|
||
|
|
* creat.c - creates a file.
|
||
|
|
*---------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
int creat(const char *path, int permission)
|
||
|
|
{
|
||
|
|
int fh, fdesc;
|
||
|
|
|
||
|
|
fdesc=_fmode; /* set RTL I/O flags */
|
||
|
|
permission^=_fmask;
|
||
|
|
if(permission == S_IREAD)
|
||
|
|
{
|
||
|
|
permission=FA_RDONLY;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
fdesc|=O_RDWR;
|
||
|
|
permission=FA_NORMAL;
|
||
|
|
}
|
||
|
|
if(_fmode&O_TEXT)
|
||
|
|
permission=FA_TEXT;
|
||
|
|
fh=_creat_trunc(path, permission); /* truncate if exists and !readonly */
|
||
|
|
if((fh < 0) || (fh >= _open_max))
|
||
|
|
return(-1);
|
||
|
|
if(isatty(fh))
|
||
|
|
fdesc|=O_DEVICE;
|
||
|
|
_openfd[fh]=fdesc; /* store file descriptor */
|
||
|
|
return(fh); /* return handle */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* open.c - opens a file. *
|
||
|
|
* This function opens a file, setting DOS access and permision modes, *
|
||
|
|
* and stores access and translation modes in the file descriptor array *
|
||
|
|
* _openfd. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
#pragma warn(wvnu => off)
|
||
|
|
|
||
|
|
int open(const char *path, int access, ...)
|
||
|
|
{
|
||
|
|
va_list varg;
|
||
|
|
int fh, fdesc;
|
||
|
|
unsigned permission;
|
||
|
|
|
||
|
|
fdesc=0;
|
||
|
|
if(access&O_TEXT) /* defaults to _fmode */
|
||
|
|
fdesc|=O_TEXT;
|
||
|
|
else if(access&O_BINARY)
|
||
|
|
fdesc|=O_BINARY;
|
||
|
|
else if( (_fmode == O_BINARY) || (_fmode == O_TEXT))
|
||
|
|
fdesc|=_fmode;
|
||
|
|
else
|
||
|
|
fdesc|=O_BINARY;
|
||
|
|
if(access&(O_CREAT|O_APPEND|O_TRUNC)) /* create append or truncate */
|
||
|
|
{
|
||
|
|
if(access&O_CREAT)
|
||
|
|
{
|
||
|
|
va_start(varg, access);
|
||
|
|
permission=va_arg(varg, unsigned); /* get permission */
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if(!(access&(O_RDWR|O_WRONLY)))
|
||
|
|
permission=S_IREAD;
|
||
|
|
else
|
||
|
|
permission=S_IREAD|S_IWRITE;
|
||
|
|
}
|
||
|
|
permission^=_fmask; /* exclusive or with fmask */
|
||
|
|
if(permission == S_IREAD) /* set DOS access modes */
|
||
|
|
{
|
||
|
|
permission=FA_RDONLY;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
fdesc|=O_RDWR;
|
||
|
|
permission=FA_NORMAL;
|
||
|
|
}
|
||
|
|
if (fdesc&O_TEXT)
|
||
|
|
permission|=FA_TEXT;
|
||
|
|
if(_exists(path)) /* does file exist ? */
|
||
|
|
{
|
||
|
|
if(access&O_EXCL)
|
||
|
|
{
|
||
|
|
errno=EEXIST;
|
||
|
|
return(-1); /* if exclusive flag return error */
|
||
|
|
}
|
||
|
|
if(!(access&O_TRUNC))
|
||
|
|
goto open_file; /* if not truncate open file */
|
||
|
|
}
|
||
|
|
else if(!(access&O_CREAT)) /* create only if flag set */
|
||
|
|
{
|
||
|
|
errno=ENOENT;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
fh=_creat_trunc(path, permission);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
open_file: /* open file */
|
||
|
|
if(!(access&(O_RDWR|O_WRONLY)))
|
||
|
|
fdesc|=O_RDONLY; /* write access given */
|
||
|
|
else
|
||
|
|
{
|
||
|
|
access&=~(O_RDONLY|O_WRONLY);
|
||
|
|
access|=O_RDWR;
|
||
|
|
fdesc|=O_RDWR;
|
||
|
|
}
|
||
|
|
access&=~(O_TEXT|O_BINARY);
|
||
|
|
if (fdesc&O_TEXT)
|
||
|
|
access|=O_TEXT;
|
||
|
|
fh=_open(path, access);
|
||
|
|
}
|
||
|
|
if((fh < 0) || (fh >= _open_max)) /* invalid handle from _open or _creat */
|
||
|
|
return(-1);
|
||
|
|
if(access&O_APPEND) /* if O_APPEND set flag */
|
||
|
|
fdesc|=O_APPEND;
|
||
|
|
if(isatty(fh)) /* check for character device */
|
||
|
|
fdesc|=O_DEVICE;
|
||
|
|
_openfd[fh]=fdesc; /* store file descriptor */
|
||
|
|
return(fh); /* return handle */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* dup.c - level 1 I/O - force duplicate file handle. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
int dup(int handle)
|
||
|
|
{
|
||
|
|
int nh;
|
||
|
|
|
||
|
|
if(((nh=_dup(handle)) == -1) || (nh >= _open_max))
|
||
|
|
return(-1); /* duplication failed */
|
||
|
|
_openfd[nh]=_openfd[handle]; /* copy file desc */
|
||
|
|
return(nh); /* success - return new handle */
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma warn(wvnu => on)
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* dup2.c - level 1 I/O - force duplicate file handle. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
int dup2(int oldhandle, int newhandle)
|
||
|
|
{
|
||
|
|
if(_openfd[newhandle]) /* close new handle if open */
|
||
|
|
close(newhandle); /* at level 1 */
|
||
|
|
if(_dup2(oldhandle, newhandle) < 0)
|
||
|
|
return(-1); /* duplication failed */
|
||
|
|
_openfd[newhandle]=_openfd[oldhandle]; /* copy file desc */
|
||
|
|
return(0); /* success - return 0 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* setmode.c - set file translation mode . *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
|
||
|
|
int setmode(int handle, unsigned mode)
|
||
|
|
{
|
||
|
|
int ret, n;
|
||
|
|
char name[P_FNAMESIZE];
|
||
|
|
|
||
|
|
if((mode != O_BINARY) && (mode != O_TEXT))
|
||
|
|
{
|
||
|
|
invalid:
|
||
|
|
errno=EINVAL;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
ret=-1;
|
||
|
|
if(_openfd[handle])
|
||
|
|
{
|
||
|
|
_FsChanToName(getRealHandle(handle),&name[0]);
|
||
|
|
if (memcmp("LOC",&name[0],3)!=0)
|
||
|
|
goto invalid;
|
||
|
|
ret=_openfd[handle]&(O_BINARY|O_TEXT); /* save old mode */
|
||
|
|
_openfd[handle]&= ~(O_BINARY|O_TEXT); /* mask out old mode */
|
||
|
|
_openfd[handle]|=mode; /* set new mode */
|
||
|
|
n=-1;
|
||
|
|
while(++n < _open_max) /* look for level 2 stream */
|
||
|
|
{
|
||
|
|
if(_iob[n]._file == handle)
|
||
|
|
{
|
||
|
|
if(mode == O_BINARY) /* Binary - set flag */
|
||
|
|
_iob[n]._flag|=_F_BIN;
|
||
|
|
else
|
||
|
|
_iob[n]._flag&=~(_F_BIN); /* Text - clear flag */
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
errno=EBADF; /* file wasn't open */
|
||
|
|
return(ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* stat and fstat - return file status information in stat structure. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
#define MAX_EXTS 4
|
||
|
|
static char exec_exts[MAX_EXTS][5]={ ".BTF", ".OPO", ".APP",".IMG"};
|
||
|
|
|
||
|
|
int stat(const char *path, struct stat *statbuf)
|
||
|
|
|
||
|
|
{
|
||
|
|
int fmode, temp, drive, fh, n;
|
||
|
|
long time;
|
||
|
|
|
||
|
|
if (!_isloc(path))
|
||
|
|
{
|
||
|
|
errno=EINVAL;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
temp=0;
|
||
|
|
fmode=_chmod(path, 0, 0); /* get access mode and file type */
|
||
|
|
if(fmode == -1)
|
||
|
|
{
|
||
|
|
errno=ENOENT;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
statbuf->st_nlink=1; /* nlink is always one */
|
||
|
|
if(fmode&0x18)
|
||
|
|
{
|
||
|
|
statbuf->st_mode=S_IFDIR;
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
temp|=S_IFREG;
|
||
|
|
if(fmode&1)
|
||
|
|
temp|=S_IREAD;
|
||
|
|
else
|
||
|
|
temp|=S_IREAD|S_IWRITE;
|
||
|
|
fh=_open(path, O_RDONLY); /* open the file */
|
||
|
|
if(fh < 0)
|
||
|
|
return(-1);
|
||
|
|
if(isatty(fh)) /* is it a device */
|
||
|
|
temp|=S_IFCHR;
|
||
|
|
else /* if it is a file get drive, length */
|
||
|
|
/* and time info plus exec status */
|
||
|
|
{
|
||
|
|
drive=_filedrive(fh);
|
||
|
|
statbuf->st_dev=drive;
|
||
|
|
statbuf->st_rdev=drive;
|
||
|
|
n=0;
|
||
|
|
while(n < MAX_EXTS)
|
||
|
|
{
|
||
|
|
if(strstr(path, exec_exts[n]))
|
||
|
|
{
|
||
|
|
temp|=S_IEXEC;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
statbuf->st_size=filelength(fh);
|
||
|
|
time=get_utime(fh);
|
||
|
|
statbuf->st_atime=time;
|
||
|
|
statbuf->st_mtime=time;
|
||
|
|
statbuf->st_ctime=time;
|
||
|
|
}
|
||
|
|
statbuf->st_mode=temp;
|
||
|
|
_close(fh); /* close the file */
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
int fstat(int handle, struct stat *statbuf)
|
||
|
|
{
|
||
|
|
int fmode, temp, drive;
|
||
|
|
long time;
|
||
|
|
|
||
|
|
temp=0;
|
||
|
|
fmode=_openfd[handle];
|
||
|
|
if(fmode == 0)
|
||
|
|
{
|
||
|
|
errno=EBADF;
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
temp|=S_IFREG; /* get access etc from file descriptor */
|
||
|
|
if(fmode&O_RDWR)
|
||
|
|
temp|=S_IREAD|S_IWRITE;
|
||
|
|
else if(fmode&O_WRONLY)
|
||
|
|
temp|=S_IWRITE;
|
||
|
|
else
|
||
|
|
temp|=S_IREAD;
|
||
|
|
if(fmode&O_DEVICE)
|
||
|
|
{
|
||
|
|
temp|=S_IFCHR;
|
||
|
|
drive=handle;
|
||
|
|
}
|
||
|
|
else /* if it is a file get length, drive */
|
||
|
|
{ /* and time info */
|
||
|
|
statbuf->st_size=filelength(handle);
|
||
|
|
time=get_utime(handle);
|
||
|
|
statbuf->st_atime=time;
|
||
|
|
statbuf->st_mtime=time;
|
||
|
|
statbuf->st_ctime=time;
|
||
|
|
drive=_filedrive(handle);
|
||
|
|
}
|
||
|
|
statbuf->st_dev=drive;
|
||
|
|
statbuf->st_rdev=drive;
|
||
|
|
statbuf->st_mode=temp;
|
||
|
|
statbuf->st_nlink=1; /* nlink is always one */
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* chsize - change size of file . *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
#define SECSIZE 2024L
|
||
|
|
|
||
|
|
int chsize(int handle, long size)
|
||
|
|
{
|
||
|
|
char *h;
|
||
|
|
int ret,mode;
|
||
|
|
|
||
|
|
if ((h=getRealHandle(handle))==NULL)
|
||
|
|
return(-1);
|
||
|
|
if ((ret=_iow3(h,P_FSETEOF,&size))<0)
|
||
|
|
{
|
||
|
|
_ioerr(ret);
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
mode=P_FABS;
|
||
|
|
_iow4(h,P_FSEEK,&mode,&size);
|
||
|
|
return(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* getcwd.c - returns pointer to buffer containing current directory. *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
char *getcwd(char *buf, int maxlen)
|
||
|
|
{
|
||
|
|
char temp[P_FNAMESIZE];
|
||
|
|
int n,p,aflag;
|
||
|
|
|
||
|
|
aflag=0;
|
||
|
|
_getPath(&temp[0]);
|
||
|
|
if(buf == NULL)
|
||
|
|
{
|
||
|
|
buf=(char *) malloc(maxlen); /* if buffer is null allocate memory */
|
||
|
|
if(buf == NULL)
|
||
|
|
{
|
||
|
|
errno=ENOMEM; /* no memory - error */
|
||
|
|
return(NULL);
|
||
|
|
}
|
||
|
|
aflag=1;
|
||
|
|
}
|
||
|
|
n=0;
|
||
|
|
p=P_FSYSNAMESIZE;
|
||
|
|
while(n < maxlen) /* copy maxlen bytes to buffer */
|
||
|
|
{
|
||
|
|
if((buf[n++]=temp[p++]) == 0)
|
||
|
|
{
|
||
|
|
if ((n=strlen(&buf[0]))!=3)
|
||
|
|
buf[n-1]=0;
|
||
|
|
return(buf);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
errno=ERANGE; /* string too long */
|
||
|
|
if(aflag) /* free heap alocated buffer */
|
||
|
|
free(buf);
|
||
|
|
return(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------------*
|
||
|
|
* console I/O *
|
||
|
|
*--------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
void cputs(const char *s)
|
||
|
|
{
|
||
|
|
int n, c;
|
||
|
|
|
||
|
|
n=0;
|
||
|
|
if(_ungotchar!=(-1))
|
||
|
|
{
|
||
|
|
putch(_ungotchar);
|
||
|
|
_ungotchar=(-1);
|
||
|
|
}
|
||
|
|
while((c=s[n++]) != 0)
|
||
|
|
{
|
||
|
|
putch(c);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|