home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 *********************************/