home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / zmodem / zm.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  18KB  |  913 lines

  1. /*
  2.  *   Z M . C
  3.  *    Copyright 1991 Omen Technology Inc All Rights Reserved
  4.  *    ZMODEM protocol primitives
  5.  *    05-24-89  Chuck Forsberg Omen Technology Inc
  6.  *
  7.  * Entry point Functions:
  8.  *    zsbhdr(type, hdr) send binary header
  9.  *    zshhdr(type, hdr) send hex header
  10.  *    zgethdr(hdr, eflag) receive header - binary or hex
  11.  *    zsdata(buf, len, frameend) send data
  12.  *    zrdata(buf, len) receive data
  13.  *    stohdr(pos) store position data in Txhdr
  14.  *    long rclhdr(hdr) recover position offset from header
  15.  * 
  16.  *
  17.  *    This version implements numerous enhancements including ZMODEM
  18.  *    Run Length Encoding and variable length headers.  These
  19.  *    features were not funded by the original Telenet development
  20.  *    contract.
  21.  * 
  22.  * This software may be freely used for non commercial and
  23.  * educational (didactic only) purposes.  This software may also
  24.  * be freely used to support file transfer operations to or from
  25.  * licensed Omen Technology products.  Any programs which use
  26.  * part or all of this software must be provided in source form
  27.  * with this notice intact except by written permission from Omen
  28.  * Technology Incorporated.
  29.  * 
  30.  * Use of this software for commercial or administrative purposes
  31.  * except when exclusively limited to interfacing Omen Technology
  32.  * products requires a per port license payment of $20.00 US per
  33.  * port (less in quantity).  Use of this code by inclusion,
  34.  * decompilation, reverse engineering or any other means
  35.  * constitutes agreement to these conditions and acceptance of
  36.  * liability to license the materials and payment of reasonable
  37.  * legal costs necessary to enforce this license agreement.
  38.  *
  39.  *
  40.  *        Omen Technology Inc        FAX: 503-621-3745
  41.  *        Post Office Box 4681
  42.  *        Portland OR 97208
  43.  *
  44.  *    This code is made available in the hope it will be useful,
  45.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  46.  *    DAMAGES OF ANY KIND.
  47.  *
  48.  */
  49.  
  50. #ifndef CANFDX
  51. #include "zmodem.h"
  52. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  53. #endif
  54.  
  55. #ifndef UNSL
  56. #define UNSL
  57. #endif
  58.  
  59.  
  60. /* Globals used by ZMODEM functions */
  61. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  62. int Rxtype;        /* Type of header received */
  63. int Rxhlen;        /* Length of header received */
  64. int Rxcount;        /* Count of data bytes received */
  65. char Rxhdr[ZMAXHLEN];    /* Received header */
  66. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  67. long Rxpos;        /* Received file position */
  68. long Txpos;        /* Transmitted file position */
  69. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  70. int Crc32t;        /* Controls 32 bit CRC being sent */
  71.             /* 1 == CRC32,  2 == CRC32 + RLE */
  72. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  73.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  74. int Usevhdrs;        /* Use variable length headers */
  75. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  76. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  77. char *Altcan;        /* Alternate canit string */
  78.  
  79. static lastsent;    /* Last char we sent */
  80. static Not8bit;        /* Seven bits seen on header */
  81.  
  82. static char *frametypes[] = {
  83.     "No Response to Error Correction Request",    /* -4 */
  84.     "No Carrier Detect",        /* -3 */
  85.     "TIMEOUT",        /* -2 */
  86.     "ERROR",        /* -1 */
  87. #define FTOFFSET 4
  88.     "ZRQINIT",
  89.     "ZRINIT",
  90.     "ZSINIT",
  91.     "ZACK",
  92.     "ZFILE",
  93.     "ZSKIP",
  94.     "ZNAK",
  95.     "ZABORT",
  96.     "ZFIN",
  97.     "ZRPOS",
  98.     "ZDATA",
  99.     "ZEOF",
  100.     "ZFERR",
  101.     "ZCRC",
  102.     "ZCHALLENGE",
  103.     "ZCOMPL",
  104.     "ZCAN",
  105.     "ZFREECNT",
  106.     "ZCOMMAND",
  107.     "ZSTDERR",
  108.     "xxxxx"
  109. #define FRTYPES 22    /* Total number of frame types in this array */
  110.             /*  not including psuedo negative entries */
  111. };
  112.  
  113. static char badcrc[] = "Bad CRC";
  114.  
  115. /* Send ZMODEM binary header hdr of type type */
  116. zsbhdr(len, type, hdr)
  117. register char *hdr;
  118. {
  119.     register int n;
  120.     register unsigned short crc;
  121.  
  122. #ifndef DSZ
  123.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  124.       frametypes[type+FTOFFSET], rclhdr(hdr));
  125. #endif
  126.     if (type == ZDATA)
  127.         for (n = Znulls; --n >=0; )
  128.             xsendline(0);
  129.  
  130.     xsendline(ZPAD); xsendline(ZDLE);
  131.  
  132.     switch (Crc32t=Txfcs32) {
  133.     case 2:
  134.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  135.         flushmo();  break;
  136.     case 1:
  137.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  138.     default:
  139.         if (Usevhdrs) {
  140.             xsendline(ZVBIN);
  141.             zsendline(len);
  142.         }
  143.         else
  144.             xsendline(ZBIN);
  145.         zsendline(type);
  146.         crc = updcrc(type, 0);
  147.  
  148.         for (n=len; --n >= 0; ++hdr) {
  149.             zsendline(*hdr);
  150.             crc = updcrc((0377& *hdr), crc);
  151.         }
  152.         crc = updcrc(0,updcrc(0,crc));
  153.         zsendline(crc>>8);
  154.         zsendline(crc);
  155.     }
  156.     if (type != ZDATA)
  157.         flushmo();
  158. }
  159.  
  160.  
  161. /* Send ZMODEM binary header hdr of type type */
  162. zsbh32(len, hdr, type, flavour)
  163. register char *hdr;
  164. {
  165.     register int n;
  166.     register UNSL long crc;
  167.  
  168.     xsendline(flavour); 
  169.     if (Usevhdrs) 
  170.         zsendline(len);
  171.     zsendline(type);
  172.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  173.  
  174.     for (n=len; --n >= 0; ++hdr) {
  175.         crc = UPDC32((0377 & *hdr), crc);
  176.         zsendline(*hdr);
  177.     }
  178.     crc = ~crc;
  179.     for (n=4; --n >= 0;) {
  180.         zsendline((int)crc);
  181.         crc >>= 8;
  182.     }
  183. }
  184.  
  185. /* Send ZMODEM HEX header hdr of type type */
  186. zshhdr(len, type, hdr)
  187. register char *hdr;
  188. {
  189.     register int n;
  190.     register unsigned short crc;
  191.  
  192. #ifndef DSZ
  193.     vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  194.       frametypes[type+FTOFFSET], rclhdr(hdr));
  195. #endif
  196.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  197.     if (Usevhdrs) {
  198.         sendline(ZVHEX);
  199.         zputhex(len);
  200.     }
  201.     else
  202.         sendline(ZHEX);
  203.     zputhex(type);
  204.     Crc32t = 0;
  205.  
  206.     crc = updcrc(type, 0);
  207.     for (n=len; --n >= 0; ++hdr) {
  208.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  209.     }
  210.     crc = updcrc(0,updcrc(0,crc));
  211.     zputhex(crc>>8); zputhex(crc);
  212.  
  213.     /* Make it printable on remote machine */
  214.     sendline(015); sendline(0212);
  215.     /*
  216.      * Uncork the remote in case a fake XOFF has stopped data flow
  217.      */
  218.     if (type != ZFIN && type != ZACK)
  219.         sendline(021);
  220.     flushmo();
  221. }
  222.  
  223. /*
  224.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  225.  */
  226. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  227. zsdata(buf, length, frameend)
  228. register char *buf;
  229. {
  230.     register unsigned short crc;
  231.  
  232. #ifndef DSZ
  233.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  234. #endif
  235.     switch (Crc32t) {
  236.     case 1:
  237.         zsda32(buf, length, frameend);  break;
  238.     case 2:
  239.         zsdar32(buf, length, frameend);  break;
  240.     default:
  241.         crc = 0;
  242.         for (;--length >= 0; ++buf) {
  243.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  244.         }
  245.         xsendline(ZDLE); xsendline(frameend);
  246.         crc = updcrc(frameend, crc);
  247.  
  248.         crc = updcrc(0,updcrc(0,crc));
  249.         zsendline(crc>>8); zsendline(crc);
  250.     }
  251.     if (frameend == ZCRCW)
  252.         xsendline(XON);
  253.     if (frameend != ZCRCG)
  254.         flushmo();
  255. }
  256.  
  257. zsda32(buf, length, frameend)
  258. register char *buf;
  259. {
  260.     register int c;
  261.     register UNSL long crc;
  262.  
  263.     crc = 0xFFFFFFFFL;
  264.     for (;--length >= 0; ++buf) {
  265.         c = *buf & 0377;
  266.         if (c & 0140)
  267.             xsendline(lastsent = c);
  268.         else
  269.             zsendline(c);
  270.         crc = UPDC32(c, crc);
  271.     }
  272.     xsendline(ZDLE); xsendline(frameend);
  273.     crc = UPDC32(frameend, crc);
  274.  
  275.     crc = ~crc;
  276.     for (c=4; --c >= 0;) {
  277.         zsendline((int)crc);  crc >>= 8;
  278.     }
  279. }
  280.  
  281. /*
  282.  * Receive array buf of max length with ending ZDLE sequence
  283.  *  and CRC.  Returns the ending character or error code.
  284.  *  NB: On errors may store length+1 bytes!
  285.  */
  286. zrdata(buf, length)
  287. register char *buf;
  288. {
  289.     register int c;
  290.     register unsigned short crc;
  291.     register char *end;
  292.     register int d;
  293.  
  294.     switch (Crc32r) {
  295.     case 1:
  296.         return zrdat32(buf, length);
  297.     case 2:
  298.         return zrdatr32(buf, length);
  299.     }
  300.  
  301.     crc = Rxcount = 0;  end = buf + length;
  302.     while (buf <= end) {
  303.         if ((c = zdlread()) & ~0377) {
  304. crcfoo:
  305.             switch (c) {
  306.             case GOTCRCE:
  307.             case GOTCRCG:
  308.             case GOTCRCQ:
  309.             case GOTCRCW:
  310.                 crc = updcrc((d=c)&0377, crc);
  311.                 if ((c = zdlread()) & ~0377)
  312.                     goto crcfoo;
  313.                 crc = updcrc(c, crc);
  314.                 if ((c = zdlread()) & ~0377)
  315.                     goto crcfoo;
  316.                 crc = updcrc(c, crc);
  317.                 if (crc & 0xFFFF) {
  318.                     zperr(badcrc);
  319.                     return ERROR;
  320.                 }
  321.                 Rxcount = length - (end - buf);
  322. #ifndef DSZ
  323.                 vfile("zrdata: %d  %s", Rxcount,
  324.                  Zendnames[d-GOTCRCE&3]);
  325. #endif
  326.                 return d;
  327.             case GOTCAN:
  328.                 zperr("Sender Canceled");
  329.                 return ZCAN;
  330.             case TIMEOUT:
  331.                 zperr("TIMEOUT");
  332.                 return c;
  333.             default:
  334.                 garbitch(); return c;
  335.             }
  336.         }
  337.         *buf++ = c;
  338.         crc = updcrc(c, crc);
  339.     }
  340. #ifdef DSZ
  341.     garbitch(); 
  342. #else
  343.     zperr("Data subpacket too long");
  344. #endif
  345.     return ERROR;
  346. }
  347.  
  348. zrdat32(buf, length)
  349. register char *buf;
  350. {
  351.     register int c;
  352.     register UNSL long crc;
  353.     register char *end;
  354.     register int d;
  355.  
  356.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  357.     while (buf <= end) {
  358.         if ((c = zdlread()) & ~0377) {
  359. crcfoo:
  360.             switch (c) {
  361.             case GOTCRCE:
  362.             case GOTCRCG:
  363.             case GOTCRCQ:
  364.             case GOTCRCW:
  365.                 d = c;  c &= 0377;
  366.                 crc = UPDC32(c, crc);
  367.                 if ((c = zdlread()) & ~0377)
  368.                     goto crcfoo;
  369.                 crc = UPDC32(c, crc);
  370.                 if ((c = zdlread()) & ~0377)
  371.                     goto crcfoo;
  372.                 crc = UPDC32(c, crc);
  373.                 if ((c = zdlread()) & ~0377)
  374.                     goto crcfoo;
  375.                 crc = UPDC32(c, crc);
  376.                 if ((c = zdlread()) & ~0377)
  377.                     goto crcfoo;
  378.                 crc = UPDC32(c, crc);
  379.                 if (crc != 0xDEBB20E3) {
  380.                     zperr(badcrc);
  381.                     return ERROR;
  382.                 }
  383.                 Rxcount = length - (end - buf);
  384. #ifndef DSZ
  385.                 vfile("zrdat32: %d %s", Rxcount,
  386.                  Zendnames[d-GOTCRCE&3]);
  387. #endif
  388.                 return d;
  389.             case GOTCAN:
  390.                 zperr("Sender Canceled");
  391.                 return ZCAN;
  392.             case TIMEOUT:
  393.                 zperr("TIMEOUT");
  394.                 return c;
  395.             default:
  396.                 garbitch(); return c;
  397.             }
  398.         }
  399.         *buf++ = c;
  400.         crc = UPDC32(c, crc);
  401.     }
  402.     zperr("Data subpacket too long");
  403.     return ERROR;
  404. }
  405.  
  406. garbitch()
  407. {
  408.     zperr("Garbled data subpacket");
  409. }
  410.  
  411. /*
  412.  * Read a ZMODEM header to hdr, either binary or hex.
  413.  *  eflag controls local display of non zmodem characters:
  414.  *    0:  no display
  415.  *    1:  display printing characters only
  416.  *    2:  display all non ZMODEM characters
  417.  *
  418.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  419.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  420.  *   Otherwise return negative on error.
  421.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  422.  */
  423. zgethdr(hdr, eflag)
  424. char *hdr;
  425. {
  426.     register int c, n, cancount;
  427.  
  428.     n = Zrwindow + Effbaud;        /* Max bytes before start of frame */
  429.     Rxframeind = Rxtype = 0;
  430.  
  431. startover:
  432.     cancount = 5;
  433. again:
  434.     /* Return immediate ERROR if ZCRCW sequence seen */
  435.     switch (c = readline(Rxtimeout)) {
  436.     case 021: case 0221:
  437.         goto again;
  438.     case RCDO:
  439.     case TIMEOUT:
  440.         goto fifi;
  441.     case CAN:
  442. gotcan:
  443.         if (--cancount <= 0) {
  444.             c = ZCAN; goto fifi;
  445.         }
  446.         switch (c = readline(1)) {
  447.         case TIMEOUT:
  448.             goto again;
  449.         case ZCRCW:
  450.             switch (readline(1)) {
  451.             case TIMEOUT:
  452.                 c = ERROR; goto fifi;
  453.             case RCDO:
  454.                 goto fifi;
  455.             default:
  456.                 goto agn2;
  457.             }
  458.         case RCDO:
  459.             goto fifi;
  460.         default:
  461.             break;
  462.         case CAN:
  463.             if (--cancount <= 0) {
  464.                 c = ZCAN; goto fifi;
  465.             }
  466.             goto again;
  467.         }
  468.     /* **** FALL THRU TO **** */
  469.     default:
  470. agn2:
  471.         if ( --n == 0) {
  472.             c = GCOUNT;  goto fifi;
  473.         }
  474.         goto startover;
  475.     case ZPAD|0200:        /* This is what we want. */
  476.         Not8bit = c;
  477.     case ZPAD:        /* This is what we want. */
  478.         break;
  479.     }
  480.     cancount = 5;
  481. splat:
  482.     switch (c = noxrd7()) {
  483.     case ZPAD:
  484.         goto splat;
  485.     case RCDO:
  486.     case TIMEOUT:
  487.         goto fifi;
  488.     default:
  489.         goto agn2;
  490.     case ZDLE:        /* This is what we want. */
  491.         break;
  492.     }
  493.  
  494.  
  495.     Rxhlen = 4;        /* Set default length */
  496.     Rxframeind = c = noxrd7();
  497.     switch (c) {
  498.     case ZVBIN32:
  499.         if ((Rxhlen = c = zdlread()) < 0)
  500.             goto fifi;
  501.         if (c > ZMAXHLEN)
  502.             goto agn2;
  503.         Crc32r = 1;  c = zrbhd32(hdr); break;
  504.     case ZBIN32:
  505.         if (Usevhdrs)
  506.             goto agn2;
  507.         Crc32r = 1;  c = zrbhd32(hdr); break;
  508.     case ZVBINR32:
  509.         if ((Rxhlen = c = zdlread()) < 0)
  510.             goto fifi;
  511.         if (c > ZMAXHLEN)
  512.             goto agn2;
  513.         Crc32r = 2;  c = zrbhd32(hdr); break;
  514.     case ZBINR32:
  515.         if (Usevhdrs)
  516.             goto agn2;
  517.         Crc32r = 2;  c = zrbhd32(hdr); break;
  518.     case RCDO:
  519.     case TIMEOUT:
  520.         goto fifi;
  521.     case ZVBIN:
  522.         if ((Rxhlen = c = zdlread()) < 0)
  523.             goto fifi;
  524.         if (c > ZMAXHLEN)
  525.             goto agn2;
  526.         Crc32r = 0;  c = zrbhdr(hdr); break;
  527.     case ZBIN:
  528.         if (Usevhdrs)
  529.             goto agn2;
  530.         Crc32r = 0;  c = zrbhdr(hdr); break;
  531.     case ZVHEX:
  532.         if ((Rxhlen = c = zgethex()) < 0)
  533.             goto fifi;
  534.         if (c > ZMAXHLEN)
  535.             goto agn2;
  536.         Crc32r = 0;  c = zrhhdr(hdr); break;
  537.     case ZHEX:
  538.         if (Usevhdrs)
  539.             goto agn2;
  540.         Crc32r = 0;  c = zrhhdr(hdr); break;
  541.     case CAN:
  542.         goto gotcan;
  543.     default:
  544.         goto agn2;
  545.     }
  546.     for (n = Rxhlen; ++n < ZMAXHLEN; )    /* Clear unused hdr bytes */
  547.         hdr[n] = 0;
  548.     Rxpos = hdr[ZP3] & 0377;
  549.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  550.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  551.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  552. fifi:
  553.     switch (c) {
  554.     case GOTCAN:
  555.         c = ZCAN;
  556.     /* **** FALL THRU TO **** */
  557.     case ZNAK:
  558.     case ZCAN:
  559.     case ERROR:
  560.     case TIMEOUT:
  561.     case RCDO:
  562.     case GCOUNT:
  563.         zperr("Got %s", frametypes[c+FTOFFSET]);
  564.     /* **** FALL THRU TO **** */
  565. #ifndef DSZ
  566.     default:
  567.         if (c >= -4 && c <= FRTYPES)
  568.             vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  569.               frametypes[c+FTOFFSET], Rxpos);
  570.         else
  571.             vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  572. #endif
  573.     }
  574.     /* Use variable length headers if we got one */
  575.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  576.         Usevhdrs = 1;
  577.     return c;
  578. }
  579.  
  580. /* Receive a binary style header (type and position) */
  581. zrbhdr(hdr)
  582. register char *hdr;
  583. {
  584.     register int c, n;
  585.     register unsigned short crc;
  586.  
  587.     if ((c = zdlread()) & ~0377)
  588.         return c;
  589.     Rxtype = c;
  590.     crc = updcrc(c, 0);
  591.  
  592.     for (n=Rxhlen; --n >= 0; ++hdr) {
  593.         if ((c = zdlread()) & ~0377)
  594.             return c;
  595.         crc = updcrc(c, crc);
  596.         *hdr = c;
  597.     }
  598.     if ((c = zdlread()) & ~0377)
  599.         return c;
  600.     crc = updcrc(c, crc);
  601.     if ((c = zdlread()) & ~0377)
  602.         return c;
  603.     crc = updcrc(c, crc);
  604.     if (crc & 0xFFFF) {
  605.         zperr(badcrc);
  606.         return ERROR;
  607.     }
  608. #ifdef ZMODEM
  609.     Protocol = ZMODEM;
  610. #endif
  611.     Zmodem = 1;
  612.     return Rxtype;
  613. }
  614.  
  615. /* Receive a binary style header (type and position) with 32 bit FCS */
  616. zrbhd32(hdr)
  617. register char *hdr;
  618. {
  619.     register int c, n;
  620.     register UNSL long crc;
  621.  
  622.     if ((c = zdlread()) & ~0377)
  623.         return c;
  624.     Rxtype = c;
  625.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  626. #ifdef DEBUGZ
  627.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  628. #endif
  629.  
  630.     for (n=Rxhlen; --n >= 0; ++hdr) {
  631.         if ((c = zdlread()) & ~0377)
  632.             return c;
  633.         crc = UPDC32(c, crc);
  634.         *hdr = c;
  635. #ifdef DEBUGZ
  636.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  637. #endif
  638.     }
  639.     for (n=4; --n >= 0;) {
  640.         if ((c = zdlread()) & ~0377)
  641.             return c;
  642.         crc = UPDC32(c, crc);
  643. #ifdef DEBUGZ
  644.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  645. #endif
  646.     }
  647.     if (crc != 0xDEBB20E3) {
  648.         zperr(badcrc);
  649.         return ERROR;
  650.     }
  651. #ifdef ZMODEM
  652.     Protocol = ZMODEM;
  653. #endif
  654.     Zmodem = 1;
  655.     return Rxtype;
  656. }
  657.  
  658.  
  659. /* Receive a hex style header (type and position) */
  660. zrhhdr(hdr)
  661. char *hdr;
  662. {
  663.     register int c;
  664.     register unsigned short crc;
  665.     register int n;
  666.  
  667.     if ((c = zgethex()) < 0)
  668.         return c;
  669.     Rxtype = c;
  670.     crc = updcrc(c, 0);
  671.  
  672.     for (n=Rxhlen; --n >= 0; ++hdr) {
  673.         if ((c = zgethex()) < 0)
  674.             return c;
  675.         crc = updcrc(c, crc);
  676.         *hdr = c;
  677.     }
  678.     if ((c = zgethex()) < 0)
  679.         return c;
  680.     crc = updcrc(c, crc);
  681.     if ((c = zgethex()) < 0)
  682.         return c;
  683.     crc = updcrc(c, crc);
  684.     if (crc & 0xFFFF) {
  685.         zperr(badcrc); return ERROR;
  686.     }
  687.     switch ( c = readline(2)) {
  688.     case 0215:
  689.         Not8bit = c;
  690.         /* **** FALL THRU TO **** */
  691.     case 015:
  692.          /* Throw away possible cr/lf */
  693.         switch (c = readline(2)) {
  694.         case 012:
  695.             Not8bit |= c;
  696.         }
  697.     }
  698. #ifdef ZMODEM
  699.     Protocol = ZMODEM;
  700. #endif
  701.     Zmodem = 1;
  702.     if (c < 0)
  703.         return c;
  704.     return Rxtype;
  705. }
  706.  
  707. /* Send a byte as two hex digits */
  708. zputhex(c)
  709. register int c;
  710. {
  711.     static char    digits[]    = "0123456789abcdef";
  712.  
  713. #ifdef DEBUGZ
  714.     if (Verbose>8)
  715.         vfile("zputhex: %02X", c);
  716. #endif
  717.     sendline(digits[(c&0xF0)>>4]);
  718.     sendline(digits[(c)&0xF]);
  719. }
  720.  
  721. /*
  722.  * Send character c with ZMODEM escape sequence encoding.
  723.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  724.  */
  725. zsendline(c)
  726. {
  727.  
  728.     /* Quick check for non control characters */
  729.     if (c & 0140)
  730.         xsendline(lastsent = c);
  731.     else {
  732.         switch (c &= 0377) {
  733.         case ZDLE:
  734.             xsendline(ZDLE);
  735.             xsendline (lastsent = (c ^= 0100));
  736.             break;
  737.         case 015:
  738.         case 0215:
  739.             if (!Zctlesc && (lastsent & 0177) != '@')
  740.                 goto sendit;
  741.         /* **** FALL THRU TO **** */
  742.         case 020:
  743.         case 021:
  744.         case 023:
  745.         case 0220:
  746.         case 0221:
  747.         case 0223:
  748.             xsendline(ZDLE);
  749.             c ^= 0100;
  750.     sendit:
  751.             xsendline(lastsent = c);
  752.             break;
  753.         default:
  754.             if (Zctlesc && ! (c & 0140)) {
  755.                 xsendline(ZDLE);
  756.                 c ^= 0100;
  757.             }
  758.             xsendline(lastsent = c);
  759.         }
  760.     }
  761. }
  762.  
  763. /* Decode two lower case hex digits into an 8 bit byte value */
  764. zgethex()
  765. {
  766.     register int c;
  767.  
  768.     c = zgeth1();
  769. #ifdef DEBUGZ
  770.     if (Verbose>8)
  771.         vfile("zgethex: %02X", c);
  772. #endif
  773.     return c;
  774. }
  775. zgeth1()
  776. {
  777.     register int c, n;
  778.  
  779.     if ((c = noxrd7()) < 0)
  780.         return c;
  781.     n = c - '0';
  782.     if (n > 9)
  783.         n -= ('a' - ':');
  784.     if (n & ~0xF)
  785.         return ERROR;
  786.     if ((c = noxrd7()) < 0)
  787.         return c;
  788.     c -= '0';
  789.     if (c > 9)
  790.         c -= ('a' - ':');
  791.     if (c & ~0xF)
  792.         return ERROR;
  793.     c += (n<<4);
  794.     return c;
  795. }
  796.  
  797. /*
  798.  * Read a byte, checking for ZMODEM escape encoding
  799.  *  including CAN*5 which represents a quick abort
  800.  */
  801. zdlread()
  802. {
  803.     register int c;
  804.  
  805. again:
  806.     /* Quick check for non control characters */
  807.     if ((c = readline(Rxtimeout)) & 0140)
  808.         return c;
  809.     switch (c) {
  810.     case ZDLE:
  811.         break;
  812.     case 023:
  813.     case 0223:
  814.     case 021:
  815.     case 0221:
  816.         goto again;
  817.     default:
  818.         if (Zctlesc && !(c & 0140)) {
  819.             goto again;
  820.         }
  821.         return c;
  822.     }
  823. again2:
  824.     if ((c = readline(Rxtimeout)) < 0)
  825.         return c;
  826.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  827.         return c;
  828.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  829.         return c;
  830.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  831.         return c;
  832.     switch (c) {
  833.     case CAN:
  834.         return GOTCAN;
  835.     case ZCRCE:
  836.     case ZCRCG:
  837.     case ZCRCQ:
  838.     case ZCRCW:
  839.         return (c | GOTOR);
  840.     case ZRUB0:
  841.         return 0177;
  842.     case ZRUB1:
  843.         return 0377;
  844.     case 023:
  845.     case 0223:
  846.     case 021:
  847.     case 0221:
  848.         goto again2;
  849.     default:
  850.         if (Zctlesc && ! (c & 0140)) {
  851.             goto again2;
  852.         }
  853.         if ((c & 0140) ==  0100)
  854.             return (c ^ 0100);
  855.         break;
  856.     }
  857.     if (Verbose>1)
  858.         zperr("Bad escape sequence %x", c);
  859.     return ERROR;
  860. }
  861.  
  862. /*
  863.  * Read a character from the modem line with timeout.
  864.  *  Eat parity, XON and XOFF characters.
  865.  */
  866. noxrd7()
  867. {
  868.     register int c;
  869.  
  870.     for (;;) {
  871.         if ((c = readline(Rxtimeout)) < 0)
  872.             return c;
  873.         switch (c &= 0177) {
  874.         case XON:
  875.         case XOFF:
  876.             continue;
  877.         default:
  878.             if (Zctlesc && !(c & 0140))
  879.                 continue;
  880.         case '\r':
  881.         case '\n':
  882.         case ZDLE:
  883.             return c;
  884.         }
  885.     }
  886. }
  887.  
  888. /* Store long integer pos in Txhdr */
  889. stohdr(pos)
  890. long pos;
  891. {
  892.     Txhdr[ZP0] = pos;
  893.     Txhdr[ZP1] = pos>>8;
  894.     Txhdr[ZP2] = pos>>16;
  895.     Txhdr[ZP3] = pos>>24;
  896. }
  897.  
  898. /* Recover a long integer from a header */
  899. long
  900. rclhdr(hdr)
  901. register char *hdr;
  902. {
  903.     register long l;
  904.  
  905.     l = (hdr[ZP3] & 0377);
  906.     l = (l << 8) | (hdr[ZP2] & 0377);
  907.     l = (l << 8) | (hdr[ZP1] & 0377);
  908.     l = (l << 8) | (hdr[ZP0] & 0377);
  909.     return l;
  910. }
  911.  
  912. /* End of zm.c */
  913.