home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pub
/
researchmachines
/
rmluti.c
< prev
Wrap
Text File
|
2020-01-01
|
14KB
|
623 lines
/************************************************************************/
/* File KUTIL2.C - Extended buffer filling/emptying procedures etc.
Chris Kennington RML. 9th July 1985 */
#define DEFS1 1
#define DEFS3 1
#define DEFS4 1
#include "stdio.h"
#include "ctype.h"
#include "b:kext.h"
/* Variables global to this file:- */
static int oldsz, oldt, qu8=0, rpt, sz;
static char *dt;
static char del1[] = {BKSP,SP,0};
static char del7[] = {BKSP,BKSP,BKSP,BKSP,BKSP,BKSP,BKSP,SP,SP,SP,SP,SP,SP,SP,0};
#ifndef MPUZ80
static char *images[] = {"7-bit stripped","8-bit binary","8th-bit prefixed",0};
#endif
extern int outfc(), outfile();
char ascch(c) /* edit out multiple CR/LFs */
/* Returns c unless redundant, when returns 0 */
char c;
{
static char oldc = 0;
c &= 0x7f; /* strip to 7 bits */
if ( ( (c == CR) && (oldc == LF) ) || ( (c == LF) && (oldc == CR) ) )
c = oldc = 0;
else {
oldc = c;
if (c == LF)
c = CR;
}
return(c);
} /* end of ascch() */
bufemp(buffer,len)
/* Puts data from an incoming packet into a file,
sleeping & waking comms & network.
If no file open (fp = 0), displays on screen
Returns 0 if OK, else contents of "errno". */
char buffer[]; /* Buffer */
int len;
{
int ret;
if (fp == 0)
ret = decode(buffer,len,outfc);
else {
s4sleep(); /* Inhibit communications */
if (list == 1)
outc('.');
ret = decode(buffer,len,outfile);
}
netcool();
return(ret);
} /* end of bufemp() */
bufill(buffer)
/* Get a bufferful of data from the file that's being sent, sleeping
* & waking comms & network.
* Traps CP/M soft EoF (ctl-Z). */
char *buffer;
{
int t;
s4sleep(); /* Inhibit communications */
errno = 0;
dt = buffer;
if (softeof) { /* Trap CP/M text-file */
sz = EOF;
goto Exit;
}
if (list == 1)
outc('.'); /* dot-printing */
rpt = sz = 0; /* Init data buffer pointer */
oldt = -2; /* impossible value */
while((t = getc(fp)) != EOF) { /* Get the next character */
/* if there is an error, getc() will also return EOF and there is an
error-code in "errno". This is picked up in sdata(). */
#ifdef MPUZ80
if (list == 2)
#else
if ( (list == 2) && (t != LF) )
#endif
outc(t);
encode(t);
if ( (image == 0) && (t == CTLZ) ) {
softeof = TRUE;
goto Exit; /* CP/M text EOF */
}
if (sz > spsiz-7) /* Check length */
goto Exit;
}
/* reach here on (hard) EOF or error */
softeof = TRUE; /* so dont reread */
if (sz==0)
sz = EOF;
Exit:
netcool();
return(sz); /* Handle partial buffer */
} /* end of bufill() */
clear5() /* clear bottom lines of screen */
{
int lin;
lin = (SCRBOT+3)*256;
while (lin < (SCRLEN*256)) {
vtline(lin,blanx);
lin += 256;
}
} /* end of clear5() */
compmode() /* display transfer modes */
{
if (image == 2)
txtout(" 8-bit data, ");
else if (oldimage == 2) {
printmsg("Warning: 8-bit transfer not agreed by remote Kermit.\r");
oldimage = image;
}
if (rptflg == TRUE)
txtout(" Compressing, ");
return;
} /* end of compmode() */
decode(buf,len,fn) /* packet decoding procedure */
/* Called with string to be decoded and an output function.
Returns 0 or error-code. */
char *buf;
int len, (*fn)();
{
char a, a7, b8, *end, rep;
int flg8=0, r, rr=0;
if (image == 2)
flg8 = -1;
end = buf + len;
while (buf < end) {
a = *buf++;
if ( rptflg && (a == '~') ) { /* got a repeat prefix? */
rep = unchar(*buf++); /* Yes, get the repeat count, */
a = *buf++; /* and get the prefixed character. */
}
else
rep = 1;
b8 = 0; /* Check high order "8th" bit */
if ( flg8 && (a == qu8) ) {
b8 = 0200;
a = *buf++; /* and get the prefixed character. */
}
if (a == quote) { /* If control prefix, */
a = *buf++; /* get its operand. */
a7 = a & 0177; /* Only look at low 7 bits. */
if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Uncontrollify */
a = ctl(a); /* if in control range. */
}
a |= b8; /* OR in the 8th bit */
while (rep-- > 0) {
r = (*fn)(a); /* Send them to the output function. */
rr |= r;
} }
return(rr);
} /* end of decode() */
encode(a)
/* encode single character into packet for transmission */
int a; /* char to be encoded */
{
int a7; /* Low order 7 bits */
int b8; /* 8th bit of character */
int flg8 = 0;
if (image == 2)
flg8 = -1;
if (rptflg) { /* repeat-count processing */
if (a == oldt) { /* char is same */
/* This algorithm is simple but relatively inefficient; it stores
the repeat flag, count and character each time around so
that when the run is broken the buffer is valid; also it
treats a pair as a run, which requires 3 bytes not 2 unless
the pair is control- or 8bit-prefixed; but it does not
require lookahead logic from the data-read. */
sz = oldsz; /* wind back pointer */
dt[sz++] = '~'; /* store prefix */
dt[sz++] = tochar(++rpt); /* & count */
if (rpt > 93) /* force new start */
oldt = -2; /* impossible value */
}
else { /* not run, or end */
rpt = 1;
oldt = a; /* save char */
oldsz = sz;
} }
a7 = a & 0177; /* Isolate ASCII part */
b8 = a & 0200; /* and 8th (parity) bit. */
if (flg8 && b8) { /* Do 8th bit prefix if necessary. */
dt[sz++] = qu8;
a = a7;
}
if ((a7 < SP) || (a7==DELT)) { /* Do control prefix if necessary */
dt[sz++] = MYQUOTE;
a = ctl(a);
}
if (a7 == MYQUOTE) /* Prefix the control prefix */
dt[sz++] = MYQUOTE;
else if (rptflg && (a7 == '~')) /* If it's the repeat prefix, */
dt[sz++] = MYQUOTE; /* quote it if doing repeat counts. */
else if (flg8 && (a7 == qu8)) /* Prefix the 8th bit prefix */
dt[sz++] = MYQUOTE; /* if doing 8th-bit prefixes */
dt[sz++] = a; /* Finally, insert the character */
dt[sz] = '\0'; /* itself, and mark the end. */
return;
} /* end of encode() */
error(fmt, a1, a2, a3, a4, a5)
/* Generate both error-message to user and if suitable
error-packet to remote. */
char *fmt;
{
int len;
sprintf(packet,fmt,a1,a2,a3,a4,a5);
printmsg(packet);
if ( (kmode == RECV) || (kmode == SEND) ) {
len = strlen(packet) + 1;
spack('E',n,len,packet);
}
return;
} /* end of error() */
/* kropen(), kwopen(), kclose():
Open and close CP/M files making necessary calls to sleep
and wake disk system & network. */
kclose(fptr) /* close file */
FILE *fptr;
{
int ret;
if (fptr == 0)
return;
bell();
++files;
s4sleep();
if ( (ret = fclose(fptr)) < 0)
printmsg(diskfail,errno); /* Aztec's error-code */
else
ret = 0;
netcool();
return(ret);
} /* end of kclose() */
FILE *kropen(name) /* open file for reading */
char name[];
{
FILE *frp;
s4sleep();
softeof = FALSE;
frp = fopen(name,"r");
netcool();
return(frp);
} /* end of fropen() */
FILE *kwopen(name) /* open file for writing */
char *name;
{
FILE *frp;
s4sleep();
frp = fopen(name,"w");
netcool();
return(frp);
} /* end of kwopen() */
/* end of open-&-close routines */
no_op() /* null routine */
{
return;
} /* End of no_op() */
outfc(ch) /* output char with control */
char ch;
/* expands tabs (every 8) and handles paging;
returns 1 if CTLC input at CR or LF, else 0. */
{
static char col=0;
char c, *more, *dlt;
if (ch < SP) switch(ch) {
/* deal with selected control-characters */
case CR:
if (kbdin() == CTLC)
return(1);
if (pager != 0)
if ( ++scrline > (pager << 2) ) {
if (col < 73) { /* room for "[more]" */
while (col++ < 73)
outc(SP);
more = "[more]";
while ( (c = *more++) != 0)
outc(c);
dlt = del7;
}
else if (col < 79) { /* no room */
while (col++ < 78)
outc(SP);
outc('*');
dlt = del1;
}
else
dlt = null;
if ( (commode & 0x02) != 0 )
nextout(XOFF); /* hold up */
while ( (c = kbdin()) == 0)
;
if ( (commode & 0x02) != 0 )
nextout(XON); /* restart */
scrline = 0;
if (c == CTLC)
return(1);
while ( (c = *dlt++) != 0)
outc(c);
}
outc(ch);
col = 0;
break;
case LF:
/* ignored - CR is expected to be treated as "newline" */
break;
case TAB:
c = 8 - (col & (char)0x07);
col &= (char)0xf8;
col += 0x08;
while (c-- > 0)
outc(SP);
break;
case BKSP:
if (col-- < 0)
col = 0;
else
outc(BKSP);
break;
default: /* pass all other controls */
outc(ch);
break;
} /* end if-switch */
else { /* normal chars */
outc(ch);
++col;
}
return(0);
} /* end of outfc() */
static int outfile(ch) /* char to file */
/* Returns 0 or error-code */
char ch;
{
int r;
r = errno = 0;
if (image == 0) /* for 7-bit transfers */
if ( (ch = ascch(ch)) == 0 ) /* CR/LF trapping */
return(0); /* ignore nulls */
else if (ch == CR) { /* CR => CR/LF */
putc(CR,fp);
if (list == 2)
outc(CR);
ch = LF;
} /* end elseif */
#ifndef MPUZ80
if ( (list == 2) && (ch != LF) )
#else
if (list == 2)
#endif
outc(ch);
if (putc(ch,fp) < 0)
r = errno; /* accumulate errors */
return(r);
} /* end of outfile() */
parex() /* exchange parameters */
/* returns 1 if successful, -1 if refused, 0 if no answer;
only allows 3 timeouts/NAKs */
{
int ln1, ln2, num, r=0, t;
ln1 = spar(packet); /* fill with ours */
forever {
spack('I',0,ln1,packet);
switch( (t = rpack(&ln2,&num,recpkt)) ) {
case 'Y': /* ACK */
rpar(recpkt,ln2); /* take theirs */
txtout(" OK ");
compmode();
n = num + 1; /* initial number */
return(1);
case 'N': /* NAK */
case FALSE: /* timeout */
if (r++ > 3)
return(0);
else
break;
default: /* protocl error */
printmsg(badmsg,'Y',t);
case 'E': /* cant cope */
return(-1);
} /* end switch */
txtout(trying);
} /* end forever */
} /* end of parex() */
rpar(data,len) /* instal received parameters safely */
char *data, len;
/* Set up incoming parameters to either what has been received
or, if nil, to defaults.
RML Kermit does not handle variable timeouts.
No return-code. */
{
char i, p;
/* initialize to defaults in case incoming block is short */
spsiz = 80; /* packet-length 80 chars */
eol = CR; /* terminator normally CR */
quote = '#'; /* standard control-quote char */
qu8 = 0; /* no 8th-bit quoting */
rptflg = 0; /* nor repeat-quoting */
/* image is not changed */
i = 0;
while (len-- > 0) {
p = data[len];
switch (len) { /* for each parameter */
case 0: /* MAXL */
spsiz = unchar(p);
break;
case 2: /* NPAD */
pad = unchar(p);
break;
case 3: /* PADC */
padchar = ctl(p);
break;
case 4: /* EOL */
eol = unchar(p);
break;
case 5: /* QCTL */
quote = p;
break;
case 6: /* QBIN */
/* 8th-bit quoting only negotiable if set by user */
i = 1;
if (image == 2) switch (p) {
case 'Y':
qu8 = '&';
break;
case 'N':
qu8 = image = 0;
break;
default:
if (isalnum(p) == 0) /* provided punctuation */
qu8 = p;
else
qu8 = image = 0;
break;
} /* end inner switch */
break;
case 8: /* REPT */
if (p == '~')
rptflg = TRUE;
break;
default: /* CHKT, CAPAS etc. */
break;
} } /* end while & outer switch */
if (i == 0) /* no data[6] */
qu8 = 0;
if ( (qu8 == 0) && (image == 2) ) /* invlaid setting */
image = 0;
if (list > 2) { /* debug only */
printf("\rDbg: Parameters in, 8th-bit setting now %d ",image);
#ifndef MPUZ80
printf("(%s)",images[image]);
if (image == 2)
printf(", prefix %c. ",qu8);
else
printf(". ");
#endif
}
return;
} /* end of rpar() */
show5(text)
/* display up to 5 lines of text at bottom of screen */
char **text;
{
char c, *hp;
int lin;
clear5(); /* clear it first */
lin = (SCRBOT+3)*256;
for (c=0; c<5; ++c) {
if ( (hp = text[c]) == 0 )
break;
vtline(lin,hp);
if ( (lin += 256) > 24*256)
break;
}
return;
} /* end of show5() */
spar(data) /* fill up packet with own parameters */
char *data;
/* returns length of parameter block (6, 7 or 9) */
{
char len;
data[0] = tochar(spsiz);
data[1] = tochar(MYTIME);
data[2] = tochar(MYPAD);
data[3] = ctl(0);
data[4] = tochar(MYEOL);
data[5] = MYQUOTE;
len = 6; /* min length */
if (image == 2) {
data[6] = 'Y'; /* feed back 8-quote */
if (qu8 == 0)
qu8 = '&';
len = 7;
}
else {
data[6] = 'N'; /* otherwise reject */
qu8 = 0;
}
if (rptflg) { /* if repeat-quoting */
data[7] = '1'; /* 1-byte checksum */
data[8] = '~'; /* only ~ for repeating*/
len = 9;
}
if (list > 2) { /* debug only */
printf("\rDbg: Parameters out, 8th-bit setting now %d ",image);
#ifndef MPUZ80
printf("(%s)",images[image]);
if (image == 2)
printf(", prefix %c. ",qu8);
else
printf(". ");
#endif
}
return(len);
} /* end of spar() */
/********************** End of KUTIL2.C **************************/