home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
S
/
ZMP-SRC.LZH
/
ZZM.C
< prev
next >
Wrap
Text File
|
2000-06-30
|
9KB
|
457 lines
/*
* Z M . C
* ZMODEM protocol primitives
* 07-28-87 Chuck Forsberg Omen Technology Inc
*
* Entry point Functions:
* zsbhdr(type, hdr) send binary header
* zshhdr(type, hdr) send hex header
* zgethdr(hdr, eflag) receive header - binary or hex
* zsdata(buf, len, frameend) send data
* zrdata(buf, len) receive data
* stohdr(pos) store position data in Txhdr
* long rclhdr(hdr) recover position offset from header
*/
#define ZM
#undef DEBUG
#include "zmp.h"
#include "zmodem.h"
#ifdef AZTEC_C
#include "libc.h"
#else
#include <stdio.h>
#endif
long updc32();
/* Send ZMODEM binary header hdr of type type */
zsbhdr(type, hdr)
char *hdr;
{
static int n;
static unsigned crc;
#ifdef DEBUG
printf("\nSending BINARY header Type %d:",type);
for (n = 0; n < 4; n++)
prhex( *(hdr + n));
printf("\n");
#endif
if (type == ZDATA)
for (n = Znulls; --n >=0; )
zsendline(0);
xmchout(ZPAD);
xmchout(ZDLE);
if (Crc32t=Txfcs32)
zsbh32(hdr, type);
else {
xmchout(ZBIN);
zsendline(type);
crc = updcrc(type, 0);
for (n=4; --n >= 0; ++hdr) {
zsendline(*hdr);
crc = updcrc((0377& *hdr), crc);
}
crc = updcrc(0,updcrc(0,crc));
zsendline(crc>>8);
zsendline(crc);
}
if (type != ZDATA)
purgeline();
}
/* Send ZMODEM binary header hdr of type type */
zsbh32(hdr, type)
char *hdr;
{
static int n;
static long crc;
xmchout(ZBIN32);
zsendline(type);
crc = 0xFFFFFFFFL;
crc = updc32(type, crc);
for (n=4; --n >= 0; ++hdr) {
crc = updc32((0377 & *hdr), crc);
zsendline(*hdr);
}
crc = ~crc;
for (n=4; --n >= 0;) {
zsendline((int)crc);
crc >>= 8;
}
}
/* Send ZMODEM HEX header hdr of type type */
zshhdr(type, hdr)
char *hdr;
{
static int n;
static unsigned crc;
#ifdef DEBUG
printf("\nSending HEX header Type %d:",type);
for (n = 0; n < 4; n++)
prhex( *(hdr + n));
printf("\n");
#endif
xmchout(ZPAD);
xmchout(ZPAD);
xmchout(ZDLE);
xmchout(ZHEX);
zputhex(type);
Crc32t = 0;
crc = updcrc(type, 0);
for (n=4; --n >= 0; ++hdr) {
zputhex(*hdr);
crc = updcrc((0377 & *hdr), crc);
}
crc = updcrc(0,updcrc(0,crc));
zputhex(crc>>8);
zputhex(crc);
/* Make it printable on remote machine */
xmchout(CR);
xmchout(LF);
/*
* Uncork the remote in case a fake XOFF has stopped data flow
*/
if (type != ZFIN && type != ZACK)
xmchout(CTRLQ);
purgeline();
}
/*
* Send binary array buf of length length, with ending ZDLE sequence frameend
*/
zsdata(buf, length, frameend)
int length, frameend;
char *buf;
{
static unsigned crc;
if (Crc32t)
zsda32(buf, length, frameend);
else {
crc = 0;
for (;--length >= 0; ++buf) {
zsendline(*buf);
crc = updcrc((0377 & *buf), crc);
}
xmchout(ZDLE);
xmchout(frameend);
crc = updcrc(frameend, crc);
crc = updcrc(0,updcrc(0,crc));
zsendline(crc>>8);
zsendline(crc);
}
if (frameend == ZCRCW) {
xmchout(XON);
purgeline();
}
}
zsda32(buf, length, frameend)
char *buf;
int length, frameend;
{
static long crc;
crc = 0xFFFFFFFFL;
for (;--length >= 0;++buf) {
crc = updc32((0377 & *buf), crc);
zsendline(*buf);
}
xmchout(ZDLE);
xmchout(frameend);
crc = updc32(frameend, crc);
crc = ~crc;
for (length=4; --length >= 0;) {
zsendline((int)crc);
crc >>= 8;
}
}
/*
* Receive array buf of max length with ending ZDLE sequence
* and CRC. Returns the ending character or error code.
* NB: On errors may store length+1 bytes!
*/
zrdata(buf, length)
char *buf;
{
static int c;
static unsigned crc;
static char *end;
static int d;
if (Rxframeind == ZBIN32)
return zrdat32(buf, length);
crc = Rxcount = 0;
end = buf + length;
while (buf <= end) {
if ((c = zdlread()) & ~0377) {
crcfoo:
switch (c) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
crc = updcrc((d=c)&0377, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updcrc(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updcrc(c, crc);
if (crc & 0xFFFF) {
zperr("Bad data CRC",TRUE);
#ifdef DEBUG
printf("\nCRC = %u\n",crc);
#endif
return NERROR;
}
Rxcount = length - (end - buf);
return d;
case GOTCAN:
zperr("Sender CANceled",TRUE);
return ZCAN;
case TIMEOUT:
zperr("TIMEOUT",TRUE);
return c;
default:
zperr("Bad data subpkt",TRUE);
return c;
}
}
*buf++ = c;
crc = updcrc(c, crc);
}
zperr("Subpkt too long",TRUE);
return NERROR;
}
zrdat32(buf, length)
char *buf;
{
static int c, d;
static long crc;
static char *end;
#ifdef DEBUG
printf("\n(32)\n");
#endif
crc = 0xFFFFFFFFL;
Rxcount = 0;
end = buf + length;
while (buf <= end) {
if ((c = zdlread()) & ~0377) {
crcfoo:
switch (c) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
d = c;
c &= 0377;
crc = updc32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updc32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updc32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updc32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updc32(c, crc);
if (crc != 0xDEBB20E3) {
zperr("Bad data CRC",TRUE);
return NERROR;
}
Rxcount = length - (end - buf);
return d;
case GOTCAN:
zperr("Sender CANceled",TRUE);
return ZCAN;
case TIMEOUT:
zperr("TIMEOUT",TRUE);
return c;
default:
zperr("Bad data subpkt",TRUE);
return c;
}
}
*buf++ = c;
crc = updc32(c, crc);
}
zperr("Subpkt too long",TRUE);
return NERROR;
}
/*
* Read a ZMODEM header to hdr, either binary or hex.
* eflag controls local display of non zmodem characters:
* 0: no display
* 1: display printing characters only
* 2: display all non ZMODEM characters
* On success, set Zmodem to 1, set Rxpos and return type of header.
* Otherwise return negative on error.
* Return NERROR instantly if ZCRCW sequence, for fast error recovery.
*/
zgethdr(hdr, eflag)
char *hdr;
int eflag;
{
static int c, n, cancount;
n = Zrwindow + Baudrate; /* Max bytes before start of frame */
Rxframeind = Rxtype = 0;
startover:
cancount = 5;
again:
/* Return immediate NERROR if ZCRCW sequence seen */
switch (c = readline(Rxtimeout)) {
case RCDO:
case TIMEOUT:
goto fifi;
case CAN:
gotcan:
if (--cancount <= 0) {
c = ZCAN;
goto fifi;
}
switch (c = readline(INTRATIME)) {
case TIMEOUT:
goto again;
case ZCRCW:
c = NERROR;
/* **** FALL THRU TO **** */
case RCDO:
goto fifi;
default:
break;
case CAN:
if (--cancount <= 0) {
c = ZCAN;
goto fifi;
}
goto again;
}
/* **** FALL THRU TO **** */
default:
agn2:
if ( --n == 0) {
zperr("Grbg ct exceeded",TRUE);
return(NERROR);
}
goto startover;
case ZPAD|0200: /* This is what we want. */
case ZPAD: /* This is what we want. */
break;
}
cancount = 5;
splat:
switch (c = noxrd7()) {
case ZPAD:
goto splat;
case RCDO:
case TIMEOUT:
goto fifi;
default:
goto agn2;
case ZDLE: /* This is what we want. */
break;
}
switch (c = noxrd7()) {
case RCDO:
case TIMEOUT:
goto fifi;
case ZBIN:
Rxframeind = ZBIN;
Crc32 = FALSE;
c = zrbhdr(hdr);
break;
case ZBIN32:
Crc32 = Rxframeind = ZBIN32;
c = zrb32hdr(hdr);
break;
case ZHEX:
Rxframeind = ZHEX;
Crc32 = FALSE;
c = zrhhdr(hdr);
break;
case CAN:
goto gotcan;
default:
goto agn2;
}
Rxpos = (unsigned)(hdr[ZP3] & 0377);
Rxpos = (Rxpos<<8) + (unsigned)(hdr[ZP2] & 0377);
Rxpos = (Rxpos<<8) + (unsigned)(hdr[ZP1] & 0377);
Rxpos = (Rxpos<<8) + (unsigned)(hdr[ZP0] & 0377);
fifi:
switch (c) {
case GOTCAN:
c = ZCAN;
/* **** FALL THRU TO **** */
case ZNAK:
case ZCAN:
case NERROR:
case TIMEOUT:
case RCDO:
sprintf(Buf,"Got %s", frametypes[c+FTOFFSET]);
zperr(Buf,TRUE);
/* **** FALL THRU TO **** */
default:
break;
}
return c;
}
#ifdef DEBUG
/* Print a byte in hex on the console */
prhex(byte)
char byte;
{
static char digits[] = "0123456789abcdef";
char hi, lo;
hi = digits[(byte & 0xf0) >> 4];
lo = digits[byte & 0x0f];
printf(" %c%c",hi,lo);
}
#endif
/***************************** End of hzm.c *********************************/