home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
163_01
/
baseio1.c
< prev
next >
Wrap
Text File
|
1988-01-31
|
16KB
|
551 lines
/*
** include baseio1.c -- base I/O routines part 1
**
** simulate UNIX I/O interfaces
**
** assumes that "errno.h" is included
** assumes that "sgtty.h" is included
** assumes that "doscall.h" is included
** assumes that "doscall.c" is included
** assumes that "heap.c" is included
** assumes that NUMFILES is defined
*/
/*
** file descriptor (handle) array
*/
static int /* would char *_filedes[] if array of * supported */
_filedes[NUMFILES];
/*
** keyboard buffer
*/
static char
kbdbuf[255];
/*
** base I/O initialization
*/
static _baseinit() {
int i;
i = 0;
while(i < NUMFILES) {
_filedes[i] = 0; /* clear pointer to DOS FCB in file descriptor array */
++i;
}
kbdbuf[0]=kbdbuf[1]=0;
errno = 0;
}
/*
** base I/O clean-up
*/
static _baseclnup() {
int i;
char *fcb;
i = 0;
while(i < NUMFILES) {
fcb = _filedes[i]; /* get address of DOS FCB */
if(*fcb != 0) _close(i); /* if file is open, close it */
++i;
}
}
/*
** open a file
*/
_open(name, mode) char *name; int mode; {
/*
** name -- path name
** mode -- 0 - read, 1 - write, 2 - read/write
** returns file descriptor
** note: always positions file to offset zero
*/
int filedes, mask;
char *fcb;
if((mode < 0) | (mode > 2)) {
errno = EINVAL; /* invalid argument */
return -1;
}
filedes = _getfcb(name); /* allocate & initialize DOS FCB */
if(filedes < 0) {
errno = EMFILE; /* too many open files */
return -1;
}
fcb = _filedes[filedes]; /* get address of DOS FCB */
fcb[FCB_MODE] = mode; /* save read/write mode */
if(mode==0) mask=2; /* read */
else if(mode==1) mask=1; /* write */
else mask=3; /* read/write */
if((mask&fcb[FCB_FLAG])!=mask) { /* if wrong device type */
_freefcb(filedes); /* free the FCB we won't be using */
errno = ENODEV;
return -1;
}
if((fcb[FCB_FLAG]&255)==255) { /* if disk file */
if(_dosfcall(F_OPEN, fcb) == 0) { /* DOS open */
fcb[FCB_LRECL] = 1; /* set "record length" to 1 */
fcb[FCB_LRECL+1] = 0;
fcb[FCB_FLGS] = 128 + 64 + 16;
fcb[FCB_FLGS+1] = 0;
return filedes;
}
else {
_freefcb(filedes); /* free the FCB we won't be using */
errno = ENOENT; /* no such file */
return -1;
}
}
else { /* not a disk file */
if(fcb[FCB_FLAG] & 192) { /* if keyboard or screen */
fcb[FCB_FLGS] = 128 + 64 + 16 + 8;
fcb[FCB_FLGS+1] = 0;
}
else if(fcb[FCB_FLAG] & 32) { /* if printer */
fcb[FCB_FLGS] = 16;
fcb[FCB_FLGS+1] = 0;
}
else if(fcb[FCB_FLAG] & 16) { /* if async */
fcb[FCB_FLGS] = 128 + 64 + 32;
fcb[FCB_FLGS+1] = 0;
}
return filedes;
}
}
/*
** create and open a file (or reopen if existing)
*/
_creat(name, mode) char *name; int mode; {
/*
** name -- path name
** mode -- file attributes -- 0 - normal, 2 - system, 4 hidden
** returns file descriptor
** note: always positions file to offset zero
** note: file is always opened for write
*/
int filedes;
char *fcb;
if((mode < 0) | (mode > 2)) {
errno = EINVAL; /* invalid argument */
return -1;
}
filedes = _getfcb(name); /* allocate & initialize DOS FCB */
if(filedes < 0) {
errno = EMFILE; /* too many open files */
return -1;
}
fcb = _filedes[filedes]; /* get address of DOS FCB */
if((fcb[FCB_FLAG]&255)!=255) { /* if not a disk file */
_freefcb(filedes); /* free the FCB we won't be using */
return _open(name, 1); /* use normal open for write */
}
fcb[FCB_ATTR] = mode; /* set file attributes */
if(_dosfcall(F_CREATE, fcb) == 0) { /* DOS create & open */
fcb[FCB_LRECL] = 1; /* set "record length" to 1 */
fcb[FCB_LRECL+1] = 0;
fcb[FCB_FLGS] = 128 + 64 + 16;
fcb[FCB_FLGS+1] = 0;
fcb[FCB_MODE] = 1; /* write only */
return filedes;
}
else {
_freefcb(filedes); /* free the FCB we won't be using */
errno = ENOSPC; /* no space in disk directory */
return -1;
}
}
/*
** close a file
*/
_close(filedes) int filedes; {
char *fcb;
int *ibuf;
if((filedes >= NUMFILES) | (filedes < 0)) {
errno = EINVAL; /* invalid argument */
return -1;
}
fcb = _filedes[filedes]; /* get address of DOS FCB */
if(fcb[FCB_FLAG] == 0) {
errno = EBADF; /* bad file number -- file not open */
return -1;
}
if((fcb[FCB_FLAG]&255) == 255) { /* if file is standard disk file */
/* if file is DOS format output (only) file, add the ctl-Z (end-of-file) */
if((fcb[FCB_FLGS]&16) && (fcb[FCB_MODE]&1)) {
_seek(filedes, 0, 5); /* find end of file */
_write(filedes, "\32", 1); /* add ctl-Z */
_iflush(fcb); /* if there is an intermediate buf, flush (ignore errors) */
ibuf = &fcb[FCB_IBUF];
if(*ibuf) free(*ibuf); /* free intermediate buffer (if any) */
}
if(_dosfcall(F_CLOSE, fcb) == 0) { /* DOS close */
_freefcb(filedes); /* free the DOS FCB */
return 0;
}
else {
errno = ENXIO; /* wrong disk may be mounted */
return -1;
}
}
else {
if(fcb[FCB_FLAG] & 32) { /* if printer */
_prnout('\f');
}
_freefcb(filedes); /* free the DOS FCB */
return 0;
}
}
/*
** read from a file
*/
_read(filedes, buffer, nbytes) int filedes, nbytes; char *buffer; {
char *fcb, ch, mode, *source, *dest;
int rcode, rbytes, count;
if((filedes >= NUMFILES) | (filedes < 0)) {
errno = EINVAL; /* invalid argument */
return -1;
}
if(nbytes <= 0) {
errno = EINVAL; /* invalid argument */
return -1;
}
fcb = _filedes[filedes]; /* get address of DOS FCB */
if(fcb[FCB_FLAG] == 0) {
errno = EBADF; /* bad file number -- file not open */
return -1;
}
if(fcb[FCB_MODE] & 128) { /* if end-of-file exists */
return 0; /* report end-of-file */
}
if((fcb[FCB_FLAG]&255) == 255) { /* if file is standard disk file */
if(fcb[FCB_MODE] & 1) { /* if not read-mode file */
errno = EBADF; /* bad file number -- file not read-mode */
return -1;
}
_dosfcall(F_SETDTA, buffer); /* set disk transfer area */
rcode = _dosfxcall(F_READ, fcb, nbytes, &rbytes); /* read the file */
if(rcode==2) {
errno = EFAULT; /* bad address range (segment wrap) */
return -1;
}
if((rcode==1) | (rcode==3)) { /* if end-of-file */
fcb[FCB_MODE] |= 128; /* remember end-of-file for next call */
}
if(fcb[FCB_FLGS] & 16) { /* if CR-LF conversion */
source = buffer;
dest = buffer;
count = rbytes;
rbytes = 0;
mode = fcb[FCB_MODE];
while(count--) {
if(*source == '\32') { /* check for ctl-Z (EOF) */
fcb[FCB_MODE] |= 128; /* set EOF flag */
break;
}
else if(*source == '\r') { /* check for CR */
if(mode & 32) { /* if prior char was LF */
mode &= ~32; /* ignore the CR */
}
else { /* prior char was not LF */
*dest++ = '\n'; /* convert CR to LF */
++rbytes;
mode |= 64; /* ignore possible following LF */
}
}
else if(*source == '\n') { /* check for LF */
if(mode & 64) { /* if prior char was CR */
mode &= ~64; /* ignore the LF */
}
else { /* prior char was not CR */
*dest++ = '\n'; /* "convert" LF to LF */
++rbytes;
mode |= 32; /* ignore possible following CR */
}
}
else{ /* none of the above */
*dest++ = *source; /* copy the character */
++rbytes;
mode &= ~(64 + 32); /* turn off CR and LF flags */
}
++source; /* next source char */
} /* end of loop */
fcb[FCB_MODE] = mode; /* save CR & LF flags */
}
return rbytes;
}
else {
if(fcb[FCB_FLAG] & 128) { /* if keyboard */
dest = buffer;
rbytes = 0;
if(fcb[FCB_FLGS] & 34) { /* if raw or half-baked */
while(rbytes < nbytes) {
ch = _kbdinc(fcb); /* read a character */
if(fcb[FCB_FLGS] & 4) { /* if fold upper to lower case */
if((ch >= 'A') & (ch <= 'Z')) ch -= ('A' - 'a');
}
if(ch=='\r') {
if(fcb[FCB_FLGS] & 16) _scrnout('\n');
ch = '\n';
}
*dest++ = ch;
++rbytes;
if(ch=='\n') break;
}
}
else { /* read keyboard a line at a time */
if(kbdbuf[0]==kbdbuf[1]) { /* if buffer is empty, fill it */
kbdbuf[0] = 255; /* size of buffer */
_dosfcall(F_BUFKBD, kbdbuf); /* read a line from kbd */
kbdbuf[0] = 0; /* number of characters read from buffer */
kbdbuf[2+(kbdbuf[1]&255)] = '\n'; /* replace CR with LF */
kbdbuf[1] += 1; /* make character count include LF */
if(fcb[FCB_FLGS] & 16) _scrnout('\n');
}
while(rbytes < nbytes) { /* read characters from buffer until enough */
++rbytes;
if((*dest++ = kbdbuf[2+(kbdbuf[0]++&255)])=='\n') break;
if(kbdbuf[0]==kbdbuf[1]) break;
}
}
/* check for ctl-Z (EOF) */
source = buffer;
count = rbytes;
rbytes = 0;
while(count--) {
if(*source++ == '\32') { /* if ctl-Z found */
fcb[FCB_MODE] |= 128; /* set EOF flag */
break;
}
++rbytes;
}
}
else if(fcb[FCB_FLAG] & 16) { /* if async */
; /* read characters from the async port */
}
if(fcb[FCB_FLGS] & 4) { /* if UPPER -> lower conversion */
source = buffer;
count = rbytes;
while(count--) {
if((*source >= 'A') & (*source <= 'Z')) {
*source += ('a' - 'A');
}
++source;
}
}
return rbytes;
}
}
/*
** read a character from the keyboard
**
** reads with/without CTRL-BREAK check
** and with/without echo
*/
static char
AL2;
static _kbdinc(fcb) char fcb[]; {
char ch;
if(fcb[FCB_FLGS] & 32) { /* if raw mode */
if(fcb[FCB_FLGS] & 8) { /* if echo */
#asm
MOV AH,6 ; direct console I/O
MOV DL,0FFH ; we are doing input
INT 021H ; call DOS
JZ $-2 ; loop until character received
MOV QAL2,AL ; put the character where we can find it
#endasm
ch = AL2;
}
else { /* no echo */
ch = _dosfcall(F_DIRNOE, 0); /* direct read with no echo */
}
}
else { /* half-baked mode */
if(fcb[FCB_FLGS] & 8) { /* if echo */
ch = _dosfcall(F_KBDECH, 0); /* read with echo */
}
else { /* no echo */
ch = _dosfcall(F_KBDNOE, 0); /* read with no echo */
}
}
return ch;
}
/*
** write to a file
*/
_write(filedes, buffer, nbytes) int filedes, nbytes; char *buffer; {
char *fcb, ch, *source;
int rcode, rbytes, *ibuf, *iptr, *icnt, count;
if((filedes >= NUMFILES) | (filedes < 0)) {
errno = EINVAL; /* invalid argument */
return -1;
}
if(nbytes < 0) { /* zero causes extension/truncation at current position */
errno = EINVAL; /* invalid argument */
return -1;
}
fcb = _filedes[filedes]; /* get address of DOS FCB */
if(fcb[FCB_FLAG] == 0) {
errno = EBADF; /* bad file number -- file not open */
return -1;
}
if((fcb[FCB_FLAG]&255) == 255) { /* if file is standard disk file */
if((fcb[FCB_MODE]&3)==0) { /* if not write-mode file */
errno = EBADF; /* bad file number -- file not write-mode */
return -1;
}
if(fcb[FCB_FLGS] & 16) { /* if CR-LF translation */
ibuf = &fcb[FCB_IBUF]; /* poor man's cast */
iptr = &fcb[FCB_IPTR];
icnt = &fcb[FCB_ICNT];
if(!*ibuf) { /* if intermediate buffer is not present */
if(!(*ibuf = *iptr = malloc(_BUFSIZE))) errno = 0;
*icnt = _BUFSIZE;
}
count = nbytes;
source = buffer;
rcode = 0;
while((count--) && !rcode) { /* process buffer into intermediate */
if(*source == '\n') { /* if char is LF (NL) */
rcode = _iwrite(fcb, '\r'); /* write a CR */
if(!rcode) rcode = _iwrite(fcb, '\n'); /* write a LF */
}
else { /* char is not LF */
rcode = _iwrite(fcb, *source); /* copy to intermediate */
}
++source;
}
}
else { /* no CR-LF translation */
_dosfcall(F_SETDTA, buffer); /* set disk transfer area */
rcode = _dosfxcall(F_WRITE, fcb, nbytes, &rbytes); /* write the file */
}
if(rcode==1) {
errno = ENOSPC; /* no room on diskette */
return -1;
}
if(rcode==2) {
errno = EFAULT; /* bad address range (segment wrap) */
return -1;
}
}
else {
rbytes = 0;
if(fcb[FCB_FLAG] & 64) { /* if screen */
while(rbytes<nbytes) {
ch = *buffer++;
if((ch=='\n') && (fcb[FCB_FLGS]&16)) _scrnout('\r');
_scrnout(ch);
++rbytes;
}
}
else if(fcb[FCB_FLAG] & 32) { /* if printer */
while(rbytes<nbytes) {
ch = *buffer++;
if((ch=='\n') && (fcb[FCB_FLGS]&16)) _prnout('\r');
_prnout(ch);
++rbytes;
}
}
else if(fcb[FCB_FLAG] & 16) { /* if async */
; /* output line to the async port */
}
}
return nbytes;
}
/*
** write a character to the intermediate buffer
*/
static _iwrite(fcb, ch) char *fcb, ch; {
int *ibuf, *iptr, *icnt, rcode, dummy;
ibuf = &fcb[FCB_IBUF]; /* poor man's cast */
iptr = &fcb[FCB_IPTR];
icnt = &fcb[FCB_ICNT];
if(*ibuf) { /* if intermediate buffer is present */
*(*iptr)++ = ch; /* store the character there */
if(--(*icnt)) { /* if buffer is full */
return _iflush(fcb); /* write the buffer */
}
else { /* the buffer still has space */
return 0;
}
}
else { /* no intermediate buffer */
_dosfcall(F_SETDTA, &ch); /* buffer = source char */
return _dosfxcall(F_WRITE, fcb, 1, &dummy); /* write one char at a time */
}
}
/*
** flush the intermediate buffer
*/
static _iflush(fcb) char *fcb {
int *ibuf, *iptr, *icnt, rcode, dummy;
ibuf = &fcb[FCB_IBUF]; /* poor man's cast */
iptr = &fcb[FCB_IPTR];
icnt = &fcb[FCB_ICNT];
if(*ibuf) { /* if intermediate buffer is present */
_dosfcall(F_SETDTA, *ibuf); /* buffer = intermediate bufer */
if(*iptr != *ibuf) /* CON can't handle zero length */
rcode = _dosfxcall(F_WRITE, fcb, (*iptr-*ibuf), &dummy);
*iptr = *ibuf; /* reset next char pointer */
*icnt = _BUFSIZE; /* reset # of chars remaining */
return rcode;
}
else {
return 0;
}
}
/*
* write a character to the screen
*/
static _scrnout(ch) char ch; {
_dosfcall(F_DSPOUT, ch);
}
/*
* write a character to the pointer
*/
static _prnout(ch) char ch; {
_dosfcall(F_PRNOUT, ch);
}