123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- /*
- * Z M . C
- * ZMODEM protocol primitives
- * 5-18-86 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
- * zsbdata(buf, len, frameend) send binary data
- * zrbdata(buf, len) receive binary data
- * stohdr(pos) store position data in Txhdr
- * long rclhdr(hdr) recover position offset from header
- */
- //#ifndef CANFDX
- #include "zmodem.h"
- int Rxtimeout = 100; /* Tenths of seconds to wait for something */
- //#endif
- #define ERROR (-1)
- static char *frametypes[] = {
- "TIMEOUT",
- "ERROR",
- "ZRQINIT",
- "ZRINIT",
- "ZSINIT",
- "ZACK",
- "ZFILE",
- "ZSKIP",
- "ZNAK",
- "ZABORT",
- "ZFIN",
- "ZRPOS",
- "ZDATA",
- "ZEOF",
- "ZFERR",
- "ZCRC",
- "ZCHALLENGE",
- "ZCOMPL",
- "ZCAN",
- "ZFREECNT",
- "ZCOMMAND",
- "ZCACK"
- #define FRTYPES 21 /* Total number of frame types in this array */
- };
- long int rclhdr(char *hdr);
- int zputhex(int c);
- int zsendline(int c);
- int zgethex(void);
- int zgeth1(void);
- int zrbhdr(char *hdr);
- int zrhhdr(char *hdr);
- int zdlread(void);
- int noxread7(void);
- /* Send ZMODEM binary header hdr of type type */
- int zsbhdr(int type, char *hdr)
- {
- int n;
- unsigned short oldcrc;
- vfile("zsbhdr: %s %lx", frametypes[type+2], rclhdr(hdr));
- xsendline(ZPAD); xsendline(ZDLE); xsendline(ZBIN);
- zsendline(type); oldcrc = updcrc(type, 0);
- for (n=4; --n >= 0;) {
- zsendline(*hdr);
- oldcrc = updcrc(*hdr++, oldcrc);
- }
- oldcrc = updcrc(0,updcrc(0,oldcrc));
- zsendline(oldcrc>>8);
- zsendline(oldcrc);
- if (type != ZDATA)
- flushmo();
- return 0;
- }
- /* Send ZMODEM HEX header hdr of type type */
- int zshhdr(int type, char *hdr)
- {
- int n;
- unsigned short oldcrc;
- vfile("zshhdr: %s %lx", frametypes[type+2], rclhdr(hdr));
-
- sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
- zputhex(type);
- oldcrc = updcrc(type, 0);
- for (n=4; --n >= 0;) {
- zputhex(*hdr); oldcrc = updcrc(*hdr++, oldcrc);
- }
- oldcrc = updcrc(0,updcrc(0,oldcrc));
- zputhex(oldcrc>>8); zputhex(oldcrc);
-
- /* Make it printable on remote machine */
- sendline(015); sendline(0212); /*012*/
- /*
- * Uncork the remote in case a fake XOFF has stopped data flow
- */
- if (type != ZFIN)
- sendline(021);
- flushmo();
- return 0;
- }
- /*
- * Send binary array buf of length length, with ending ZDLE sequence frameend
- */
- int zsbdata(char *buf, int length, int frameend)
- {
- register unsigned short oldcrc;
- vfile("zsbdata: length=%d end=%x", length, frameend);
- oldcrc = 0;
- for (;--length >= 0;) {
- zsendline(*buf);
- oldcrc = updcrc(*buf++, oldcrc);
- }
- xsendline(ZDLE); xsendline(frameend);
- oldcrc = updcrc(frameend, oldcrc);
- oldcrc = updcrc(0,updcrc(0,oldcrc));
- zsendline(oldcrc>>8);
- zsendline(oldcrc);
- if (frameend == ZCRCW)
- flushmo();
- return 0;
- }
- /*
- * Receive binary array buf of max length with ending ZDLE sequence
- * and CRC. Returns the ending character or error code.
- */
- int zrbdata(char *buf, int length)
- {
- int c;
- unsigned short oldcrc;
- int d;
- oldcrc = Rxcount = 0;
- for (;;) {
- if ((c = zdlread()) & ~0377) {
- switch (c) {
- case GOTCRCE:
- case GOTCRCG:
- case GOTCRCQ:
- case GOTCRCW:
- oldcrc = updcrc((d=c)&0377, oldcrc);
- if ((c = zdlread()) & ~0377)
- goto badcrc;
- oldcrc = updcrc(c, oldcrc);
- if ((c = zdlread()) & ~0377)
- goto badcrc;
- oldcrc = updcrc(c, oldcrc);
- if (oldcrc & 0xFFFF) {
- badcrc:
- zperr("Bad data packet CRC");
- return ERROR;
- }
- vfile("zrbdata: Rxcount = %d ret = %x",
- Rxcount, d);
- return d;
- case GOTCAN:
- zperr("ZMODEM: Sender Canceled");
- return ZCAN;
- case TIMEOUT:
- zperr("ZMODEM data packet TIMEOUT");
- return c;
- default:
- zperr("ZMODEM bad data packet ret=%x", c);
- return c;
- }
- }
- if (--length < 0) {
- zperr("ZMODEM binary data packet too long");
- return ERROR;
- }
- ++Rxcount;
- *buf++ = c;
- oldcrc = updcrc(c, oldcrc);
- continue;
- }
- }
- /*
- * 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 and return type of header.
- * Otherwise return negative on error
- */
- int zgethdr(char *hdr, int eflag)
- {
- int c, n;
- n = Baudrate; /* Max characters before start of frame */
- again:
- Rxframeind = Rxtype = 0;
- switch (c = noxread7()) {
- case TIMEOUT:
- goto fifi;
- case ZDLE:
- if (noxread7() == ZDLE) {
- c = ZCAN; goto fifi;
- }
- /* **** FALL THRU TO **** */
- default:
- if ( --n == 0) {
- zperr("ZMODEM Garbage count exceeded");
- return(ERROR);
- }
- if (eflag && ((c &= 0177) & 0140))
- bttyout(c);
- else if (eflag > 1)
- bttyout(c);
- goto again;
- case ZPAD:
- break;
- }
- splat:
- switch (c = noxread7()) {
- case ZPAD:
- goto splat;
- case TIMEOUT:
- goto fifi;
- default:
- goto again;
- case ZDLE:
- break;
- }
- switch (c = noxread7()) {
- case TIMEOUT:
- goto fifi;
- case ZBIN:
- Rxframeind = ZBIN;
- c = zrbhdr(hdr);
- break;
- case ZHEX:
- Rxframeind = ZHEX;
- c = zrhhdr(hdr);
- break;
- case ZDLE:
- if (noxread7() == ZDLE) {
- c = ZCAN; goto fifi;
- }
- /* **** FALL THRU TO **** */
- default:
- goto again;
- }
- Rxpos = hdr[ZP3] & 0377;
- Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
- Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
- Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
- fifi:
- switch (c) {
- case GOTCAN:
- c = ZCAN;
- /* **** FALL THRU TO **** */
- case ZNAK:
- case ZCAN:
- case ERROR:
- case TIMEOUT:
- zperr("ZMODEM: Got %s header", frametypes[c+2]);
- default:
- if (c >= -2 && c <= FRTYPES)
- vfile("zgethdr: %s %lx", frametypes[c+2], Rxpos);
- else
- vfile("zgethdr: %d %lx", c, Rxpos);
- }
- return c;
- }
- /* Receive a binary style header (type and position) */
- int zrbhdr(char *hdr)
- {
- int c, n;
- unsigned short oldcrc;
- if ((c = zdlread()) & ~0377)
- return c;
- Rxtype = c;
- oldcrc = updcrc(c, 0);
- for (n=4; --n >= 0;) {
- if ((c = zdlread()) & ~0377)
- return c;
- oldcrc = updcrc(c, oldcrc);
- *hdr++ = c;
- }
- if ((c = zdlread()) & ~0377)
- return c;
- oldcrc = updcrc(c, oldcrc);
- if ((c = zdlread()) & ~0377)
- return c;
- oldcrc = updcrc(c, oldcrc);
- if (oldcrc & 0xFFFF) {
- zperr("Bad Header CRC"); return ERROR;
- }
- Zmodem = 1;
- return Rxtype;
- }
- /* Receive a hex style header (type and position) */
- int zrhhdr(char *hdr)
- {
- int c;
- unsigned short oldcrc;
- int n;
- if ((c = zgethex()) < 0)
- return c;
- Rxtype = c;
- oldcrc = updcrc(c, 0);
- for (n=4; --n >= 0;) {
- if ((c = zgethex()) < 0)
- return c;
- oldcrc = updcrc(c, oldcrc);
- *hdr++ = c;
- }
- if ((c = zgethex()) < 0)
- return c;
- oldcrc = updcrc(c, oldcrc);
- if ((c = zgethex()) < 0)
- return c;
- oldcrc = updcrc(c, oldcrc);
- if (oldcrc & 0xFFFF) {
- zperr("Bad Header CRC"); return ERROR;
- }
- if (readline(1) == '\r') /* Throw away possible cr/lf */
- readline(1);
- Zmodem = 1; return Rxtype;
- }
- /* Send a byte as two hex digits */
- int zputhex(int c)
- {
- static char digits[] = "0123456789abcdef";
- if (Verbose>4)
- vfile("zputhex: %x", c);
- sendline(digits[(c&0xF0)>>4]);
- sendline(digits[(c)&0xF]);
- return 0;
- }
- /* Send character c with ZMODEM escape sequence encoding */
- int zsendline(int c)
- {
- switch (c & 0377) {
- case ZDLE:
- case 021:
- case 023:
- case 0221:
- case 0223:
- xsendline(ZDLE);
- c ^= 0100;
- /* **** FALL THRU TO **** */
- default:
- xsendline(c);
- }
- return 0;
- }
- /* Decode two lower case hex digits into an 8 bit byte value */
- int zgethex(void)
- {
- int c;
- c = zgeth1();
- if (Verbose>4)
- vfile("zgethex: %x", c);
- return c;
- }
- int zgeth1(void)
- {
- int c, n;
- if ((c = noxread7()) < 0)
- return c;
- n = c - '0';
- if (n > 9)
- n -= ('a' - ':');
- if (n & ~0xF)
- return ERROR;
- if ((c = noxread7()) < 0)
- return c;
- c -= '0';
- if (c > 9)
- c -= ('a' - ':');
- if (c & ~0xF)
- return ERROR;
- c += (n<<4);
- return c;
- }
- /*
- * Read a byte, checking for ZMODEM escape encoding
- * including CAN-CAN which represents a quick abort
- */
- int zdlread(void)
- {
- int c;
- if ((c = readline(Rxtimeout)) != ZDLE)
- return c;
- if ((c = readline(Rxtimeout)) < 0)
- return c;
- switch (c) {
- case ZDLE:
- return GOTCAN;
- case ZCRCE:
- case ZCRCG:
- case ZCRCQ:
- case ZCRCW:
- return (c | GOTOR);
- case ZRUB0:
- return 0177;
- case ZRUB1:
- return 0377;
- default:
- if ((c & 0140) == 0100)
- return (c ^ 0100);
- break;
- }
- zperr("Got bad ZMODEM escape sequence %x", c);
- return ERROR;
- }
- /*
- * Read a character from the modem line with timeout.
- * Eat parity, XON and XOFF characters.
- */
- int noxread7(void)
- {
- int c;
- for (;;) {
- if ((c = readline(Rxtimeout)) < 0)
- return c;
- switch (c &= 0177) {
- case XON:
- case XOFF:
- continue;
- default:
- return c;
- }
- }
- }
- /* Store long integer pos in Txhdr */
- int stohdr(long int pos)
- {
- Txhdr[ZP0] = pos;
- Txhdr[ZP1] = pos>>8;
- Txhdr[ZP2] = pos>>16;
- Txhdr[ZP3] = pos>>24;
- return 0;
- }
- /* Recover a long integer from a header */
- long
- int rclhdr(char *hdr)
- {
- long int l;
- l = (hdr[ZP3] & 0377);
- l = (l << 8) | (hdr[ZP2] & 0377);
- l = (l << 8) | (hdr[ZP1] & 0377);
- l = (l << 8) | (hdr[ZP0] & 0377);
- return l;
- }
|