home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / ZM.C < prev    next >
C/C++ Source or Header  |  1993-02-20  |  24KB  |  1,062 lines

  1. /****************************************************************************
  2. *    Language     :    Turbo C 2.0                                                *
  3. *    Logfile        :    zm.c                                                    *
  4. *    Project        :    Comms Library.                                            *
  5. *    Date         :    25 Jan 90                                                *
  6. *    Revision     :    1.1        GT    PC version.                                    *
  7. *    25 Oct 92    :    1.2        GT    KA9Q mods.                                    *
  8. *****************************************************************************
  9. *    Purpose        :    ZMODEM protocol primitives.                                *
  10. *****************************************************************************
  11. *                :    This module is based on the equivalent module in the    *
  12. *                :    31 Aug 87 version of rz/sz.                                *
  13. *    $Id: zm.c 1.1 93/01/16 18:38:59 ROOT_DOS Exp $
  14. ****************************************************************************/
  15.  
  16. /*
  17.  *   Z M . C
  18.  *    ZMODEM protocol primitives
  19.  *    07-28-87  Chuck Forsberg Omen Technology Inc
  20.  *
  21.  * Entry point Functions:
  22.  *    _zsbhdr (type, hdr) send binary header
  23.  *    _zshhdr (type, hdr) send hex header
  24.  *    _zgethdr (hdr, eflag) receive header - binary or hex
  25.  *    _zsdata (buf, len, frameend) send data
  26.  *    _zrdata (buf, len) receive data
  27.  *    _stohdr (pos) store position data in _Txhdr
  28.  *    long _rclhdr (hdr) recover position offset from header
  29.  */
  30.  
  31. #ifndef CANFDX
  32. #include    "zmodem.h"
  33.  
  34. int _Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  35. #endif
  36.  
  37. #include    <setjmp.h>
  38. #include    "sz.h"
  39. #include    "zm.h"
  40. #include    "rbsb.h"
  41.  
  42.  
  43. #ifndef UNSL
  44. #define UNSL    unsigned
  45. #endif
  46.  
  47.  
  48. /****************************************************************************
  49. *    Local prototypes.                                                        *
  50. ****************************************************************************/
  51.  
  52. static int noxrd7 (void);
  53. static int zdlread (void);
  54. static int zgeth1 (void);
  55. static int zgethex (void);
  56. static void zputhex (int c);
  57. static int zrbhdr (char *hdr);
  58. static int zrbhdr32 (char *hdr);
  59. static int zrdat32 (char *buf, int length);
  60. static int zrhhdr (char *hdr);
  61. static void zsbh32 (char *hdr, int type);
  62. static void zsda32 (char *buf, int length, int frameend);
  63. static void zsendline (int c);
  64.  
  65.  
  66. /****************************************************************************
  67. *    Globals used by ZMODEM functions.                                        *
  68. ****************************************************************************/
  69.  
  70. static int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame received    */
  71. static int Rxtype;            /* Type of header received                         */
  72. int _Rxcount;                /* Count of data bytes received                 */
  73. char _Rxhdr[4];                /* Received header                                 */
  74. char _Txhdr[4];                /* Transmitted header                             */
  75. long _Rxpos;                /* Received file position                         */
  76. long _Txpos;                /* Transmitted file position                     */
  77. int _Txfcs32;                /* TRUE - send binary frames with 32 bit FCS     */
  78. int _Crc32t;                /* Display flag - 32 bit CRC being sent         */
  79. int _Crc32;                    /* Display flag - 32 bit CRC being received        */
  80. int _Znulls;                    /* No of nulls to send at start of ZDATA hdr    */
  81. char _Attn[ZATTNLEN + 1];    /* Attention string rx sends to tx on err        */
  82.  
  83.  
  84. static char *frametypes[] =
  85.     {
  86.     "Carrier Lost",            /* -3 */
  87.     "TIMEOUT",                /* -2 */
  88.     "ERROR",                /* -1 */
  89. #define FTOFFSET     3
  90.     "ZRQINIT",
  91.     "ZRINIT",
  92.     "ZSINIT",
  93.     "ZACK",
  94.     "ZFILE",
  95.     "ZSKIP",
  96.     "ZNAK",
  97.     "ZABORT",
  98.     "ZFIN",
  99.     "ZRPOS",
  100.     "ZDATA",
  101.     "ZEOF",
  102.     "ZFERR",
  103.     "ZCRC",
  104.     "ZCHALLENGE",
  105.     "ZCOMPL",
  106.     "ZCAN",
  107.     "ZFREECNT",
  108.     "ZCOMMAND",
  109.     "ZSTDERR",
  110.     "xxxxx"
  111. #define FRTYPES 22            /* Total number of frame types in this array    */
  112.                             /*  not including psuedo negative entries        */
  113.     };
  114.  
  115.  
  116. /****************************************************************************
  117. *    _zsbhdr                                                                    *
  118. *    Send ZMODEM binary header <hdr> of type <type>.                            *
  119. ****************************************************************************/
  120.  
  121. void _zsbhdr (int type, char *hdr)
  122.     {
  123.     int n;
  124.     unsigned short crc;
  125.  
  126.     _vfile ("_zsbhdr: %s %lx", frametypes[type + FTOFFSET], _rclhdr (hdr));
  127.     if (type == ZDATA)
  128.         for (n = _Znulls; --n >= 0;)
  129.             zsendline (0);
  130.  
  131.     _xsendline (ZPAD);
  132.     _xsendline (ZDLE);
  133.  
  134.     if ((_Crc32t = _Txfcs32) != 0)
  135.         zsbh32 (hdr, type);
  136.     else
  137.         {
  138.         _xsendline (ZBIN);
  139.         zsendline (type);
  140.         crc = updcrc (type, 0);
  141.  
  142.         for (n = 4; --n >= 0; ++hdr)
  143.             {
  144.             zsendline (*hdr);
  145.             crc = updcrc ((0377 & *hdr), crc);
  146.             }
  147.             
  148.         crc = updcrc (0, updcrc (0, crc));
  149.         zsendline (crc >> 8);
  150.         zsendline (crc);
  151.         }
  152.  
  153.     if (type != ZDATA)
  154.         _flushmo ();
  155.  
  156.     }    /* void _zsbhdr (int type, char *hdr) */
  157.     
  158.  
  159. /****************************************************************************
  160. *    zsbh32                                                                    *
  161. *    Send ZMODEM binary header <hdr> of type <type>.                            *
  162. ****************************************************************************/
  163.  
  164. static void zsbh32 (char *hdr, int type)
  165.     {
  166.     int n;
  167.     UNSL long crc;
  168.  
  169.     _xsendline (ZBIN32);
  170.     zsendline (type);
  171.     crc = 0xFFFFFFFFL;
  172. #ifdef    DEBUGZ
  173.     _vfile ("\n%s:%d zsbh32 initial CRC = %08lx", __FILE__, __LINE__, crc);
  174. #endif
  175.     crc = UPDC32 (type, crc);
  176. #ifdef    DEBUGZ
  177.     _vfile ("%s:%d zsbh32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  178.            type, crc);
  179. #endif
  180.  
  181.     for (n = 4; --n >= 0; ++hdr)
  182.         {
  183.         crc = UPDC32 ((0377 & *hdr), crc);
  184. #ifdef    DEBUGZ
  185.         _vfile ("%s:%d zsbh32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  186.                (0377 & *hdr), crc);
  187. #endif
  188.         zsendline (*hdr);
  189.         }
  190.         
  191.     crc = ~crc;
  192. #ifdef    DEBUGZ
  193.     _vfile ("%s:%d zsbh32 sent CRC = %08lx", __FILE__, __LINE__, crc);
  194. #endif
  195.     for (n = 4; --n >= 0;)
  196.         {
  197.         zsendline ((int) crc);
  198.         crc >>= 8;
  199.         }
  200.         
  201.     }    /* static void zsbh32 (char *hdr, int type) */
  202.     
  203.  
  204. /****************************************************************************
  205. *    _zshhdr                                                                    *
  206. *    Send ZMODEM HEX header <hdr> of type <type>.                            *
  207. ****************************************************************************/
  208.  
  209. void _zshhdr (int type, char *hdr)
  210.     {
  211.     int n;
  212.     unsigned short crc;
  213.  
  214.     _vfile ("_zshhdr: %s %lx", frametypes[type + FTOFFSET], _rclhdr (hdr));
  215.     _sendline (ZPAD);
  216.     _sendline (ZPAD);
  217.     _sendline (ZDLE);
  218.     _sendline (ZHEX);
  219.     zputhex (type);
  220.     _Crc32t = 0;
  221.  
  222.     crc = updcrc (type, 0);
  223.     for (n = 4; --n >= 0; ++hdr)
  224.         {
  225.         zputhex (*hdr);
  226.         crc = updcrc ((0377 & *hdr), crc);
  227.         }
  228.  
  229.     crc = updcrc (0, updcrc (0, crc));
  230.     zputhex (crc >> 8);
  231.     zputhex (crc);
  232.  
  233.     /* Make it printable on remote machine */
  234.  
  235.     _sendline (015);
  236.     _sendline (012);
  237.  
  238.     /* Uncork the remote in case a fake XOFF has stopped data flow. */
  239.     
  240.     if (type != ZFIN && type != ZACK)
  241.         _sendline (021);
  242.  
  243.     _flushmo ();
  244.     }    /* void _zshhdr (int type, char *hdr) */
  245.     
  246.  
  247. /****************************************************************************
  248. *    _zsdata                                                                    *
  249. *    Send binary array <buf> of length <length>, with ending ZDLE sequence     *
  250. *    <frameend>.                                                                *
  251. ****************************************************************************/
  252.  
  253. void _zsdata (char *buf, int length, int frameend)
  254.     {
  255.     unsigned short crc;
  256.  
  257.     _vfile ("_zsdata: length=%d end=%x", length, frameend);
  258.     if (_Crc32t)
  259.         zsda32 (buf, length, frameend);
  260.     else
  261.         {
  262.         crc = 0;
  263.         for (;--length >= 0; ++buf)
  264.             {
  265.             zsendline (*buf);
  266.             crc = updcrc ((0377 & *buf), crc);
  267.             }
  268.  
  269.         _xsendline (ZDLE);
  270.         _xsendline (frameend);
  271.         crc = updcrc (frameend, crc);
  272.  
  273.         crc = updcrc (0, updcrc (0, crc));
  274.         zsendline (crc >> 8);
  275.         zsendline (crc);
  276.         }
  277.  
  278.     if (frameend == ZCRCW)
  279.         {
  280.         _xsendline (XON);
  281.         _flushmo ();
  282.         }
  283.         
  284.     }    /* void _zsdata (char *buf, int length, int frameend) */
  285.     
  286.  
  287. /****************************************************************************
  288. *    zsda32                                                                    *
  289. *    Send <length> bytes from <buf> followed by ZDLE <frameend> with a 32    *
  290. *    bit CRC.                                                                *
  291. ****************************************************************************/
  292.  
  293. static void zsda32 (char *buf, int length, int frameend)
  294.     {
  295.     UNSL long crc;
  296.  
  297.     crc = 0xFFFFFFFFL;
  298. #ifdef    DEBUGZ
  299.     _vfile ("\n%s:%d zsda32 initial CRC = %08lx", __FILE__, __LINE__, crc);
  300. #endif
  301.     for (;--length >= 0; ++buf)
  302.         {
  303.         crc = UPDC32 ((0377 & *buf), crc);
  304. #if    0
  305.         _vfile ("%s:%d zsda32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  306.                (0377 & *buf), crc);
  307. #endif
  308.         zsendline (*buf);
  309.         }
  310.  
  311.     _xsendline (ZDLE);
  312.     _xsendline (frameend);
  313.     crc = UPDC32 (frameend, crc);
  314. #ifdef    DEBUGZ
  315.     _vfile ("%s:%d zsda32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  316.            frameend, crc);
  317. #endif
  318.  
  319.     crc = ~crc;
  320. #ifdef    DEBUGZ
  321.     _vfile ("%s:%d zsda32 sent CRC = %08lx", __FILE__, __LINE__, crc);
  322. #endif
  323.     for (length = 4; --length >= 0;)
  324.         {
  325.         zsendline ((int) crc);
  326.         crc >>= 8;
  327.         }
  328.  
  329.     }    /* static void zsda32 (char *buf, int length, int frameend) */
  330.     
  331.  
  332. /****************************************************************************
  333. *    _zrdata                                                                    *
  334. *    Receive array <buf> of max <length> with ending ZDLE sequence and CRC.    *
  335. *    Returns the ending character or error code.  NB: On errors may store     *
  336. *    <length> + 1 bytes!                                                        *
  337. ****************************************************************************/
  338.  
  339. int _zrdata (char *buf, int length)
  340.     {
  341.     int c;
  342.     unsigned short crc;
  343.     char *end;
  344.     int d;
  345.  
  346.     if (Rxframeind == ZBIN32)
  347.         return zrdat32 (buf, length);
  348.  
  349.     crc = _Rxcount = 0;
  350.     end = buf + length;
  351.     while (buf <= end)
  352.         {
  353.         if ((c = zdlread ()) & ~0377)
  354.             {
  355. crcfoo:
  356.            switch (c)
  357.                 {
  358.                 case GOTCRCE:
  359.                 case GOTCRCG:
  360.                 case GOTCRCQ:
  361.                 case GOTCRCW:
  362.                     crc = updcrc (((d = c) & 0377), crc);
  363.                     if ((c = zdlread ()) & ~0377)
  364.                         goto crcfoo;
  365.  
  366.                     crc = updcrc (c, crc);
  367.                     if ((c = zdlread ()) & ~0377)
  368.                         goto crcfoo;
  369.  
  370.                     crc = updcrc (c, crc);
  371.                     if (crc & 0xFFFF)
  372.                         {
  373.                         _zperr_ ("Bad data CRC");
  374.                         return ERROR;
  375.                         }
  376.  
  377.                     _Rxcount = (int) (length - (end - buf));
  378.                     _vfile ("_zrdata: cnt = %d ret = %x", _Rxcount, d);
  379.                     return d;
  380.  
  381.                 case GOTCAN:
  382.                     _zperr_ ("Sender cancelled");
  383.                     return ZCAN;
  384.  
  385.                 case ZTIMEOUT:
  386.                     _zperr_ ("TIMEOUT");
  387.                     return c;
  388.  
  389.                 default:
  390.                     _zperr_ ("Bad data subpacket");
  391.                     return c;
  392.                 }    /* switch (c) */
  393.                 
  394.             }    /* if ((c = zdlread ()) & ~0377) */
  395.             
  396.         *buf++ = (char) c;
  397.         crc = updcrc (c, crc);
  398.         }    /* while (buf <= end) */
  399.         
  400.     _zperr_ ("Data subpacket too long");
  401.     return ERROR;
  402.     }    /* int _zrdata (char *buf, int length) */
  403.     
  404.  
  405. /****************************************************************************
  406. *    zrdat32                                                                    *
  407. *    As _zrdata with 32 bit CRC.                                                *
  408. ****************************************************************************/
  409.  
  410. static int zrdat32 (char *buf, int length)
  411.     {
  412.     int c;
  413.     UNSL long crc;
  414.     char *end;
  415.     int d;
  416.  
  417.     crc = 0xFFFFFFFFL;
  418.     _Rxcount = 0;
  419.     end = buf + length;
  420.     while (buf <= end)
  421.         {
  422.         if ((c = zdlread ()) & ~0377)
  423.             {
  424. crcfoo:
  425.            switch (c)
  426.                 {
  427.                 case GOTCRCE:
  428.                 case GOTCRCG:
  429.                 case GOTCRCQ:
  430.                 case GOTCRCW:
  431.                     d = c;
  432.                     c &= 0377;
  433.                     crc = UPDC32 (c, crc);
  434.                     if ((c = zdlread ()) & ~0377)
  435.                         goto crcfoo;
  436.  
  437.                     crc = UPDC32 (c, crc);
  438.                     if ((c = zdlread ()) & ~0377)
  439.                         goto crcfoo;
  440.  
  441.                     crc = UPDC32 (c, crc);
  442.                     if ((c = zdlread ()) & ~0377)
  443.                         goto crcfoo;
  444.  
  445.                     crc = UPDC32 (c, crc);
  446.                     if ((c = zdlread ()) & ~0377)
  447.                         goto crcfoo;
  448.  
  449.                     crc = UPDC32 (c, crc);
  450.                     if (crc != 0xDEBB20E3L)
  451.                         {
  452.                         _zperr_ ("Bad data CRC");
  453.                         return ERROR;
  454.                         }
  455.  
  456.                     _Rxcount = (int) (length - (end - buf));
  457.                     _vfile ("zrdat32: cnt = %d ret = %x", _Rxcount, d);
  458.                     return d;
  459.  
  460.                 case GOTCAN:
  461.                     _zperr_ ("Sender cancelled");
  462.                     return ZCAN;
  463.  
  464.                 case ZTIMEOUT:
  465.                     _zperr_ ("TIMEOUT");
  466.                     return c;
  467.  
  468.                 default:
  469.                     _zperr_ ("Bad data subpacket");
  470.                     return c;
  471.                 }    /* switch (c) */
  472.                 
  473.             }    /* if ((c = zdlread ()) & ~0377) */
  474.             
  475.         *buf++ = (char) c;
  476.         crc = UPDC32 (c, crc);
  477.         }    /* while (buf <= end) */
  478.         
  479.     _zperr_ ("Data subpacket too long");
  480.     return ERROR;
  481.     }    /* static int zrdat32 (char *buf, int length) */
  482.     
  483.  
  484. /****************************************************************************
  485. *    _zgethdr                                                                    *
  486. *    Read a ZMODEM header to <hdr>, either binary or hex.  <eflag> controls    *
  487. *    local display of non zmodem characters:                                    *
  488. *    0:  no display                                                            *
  489. *    1:  display printing characters only                                    *
  490. *    2:  display all non ZMODEM characters                                    *
  491. *     On success, set Zmodem to 1, set _Rxpos and return type of header.        *
  492. *    Otherwise return negative on error.                                        *
  493. *    Return ERROR instantly if ZCRCW sequence, for fast error recovery.        *
  494. ****************************************************************************/
  495.  
  496. int _zgethdr (char *hdr, int eflag)
  497.     {
  498.     int c, n, cancount;
  499.  
  500.     n = _Zrwindow + _Baud_z;            /* Max bytes before start of frame    */
  501.     Rxframeind = Rxtype = 0;
  502.  
  503. startover:
  504.     cancount = 5;
  505.     
  506. again:
  507.     /* Return immediate ERROR if ZCRCW sequence seen */
  508.     
  509.     switch (c = _readline (_Rxtimeout))
  510.         {
  511.         case RCDO:
  512.         case ZTIMEOUT:
  513.             goto fifi;
  514.  
  515.         case CAN:
  516. gotcan:
  517.            if (--cancount <= 0)
  518.                 {
  519.                 c = ZCAN;
  520.                 goto fifi;
  521.                 }
  522.  
  523.             switch (c = _readline (1))
  524.                 {
  525.                 case ZTIMEOUT:
  526.                     goto again;
  527.  
  528.                 case ZCRCW:
  529.                     c = ERROR;
  530.  
  531.                     /* **** FALL THRU TO **** */
  532.  
  533.                 case RCDO:
  534.                     goto fifi;
  535.  
  536.                 default:
  537.                     break;
  538.  
  539.                 case CAN:
  540.                     if (--cancount <= 0)
  541.                         {
  542.                         c = ZCAN;
  543.                         goto fifi;
  544.                         }
  545.  
  546.                     goto again;
  547.                 }    /* switch (c = _readline (1)) */
  548.                 
  549.         /* **** FALL THRU TO **** */
  550.  
  551.         default:
  552. agn2:
  553.            if (--n == 0)
  554.                 {
  555.                 _zperr_ ("Garbage count exceeded");
  556.                 return (ERROR);
  557.                 }
  558.  
  559.             if (eflag && ((c &= 0177) & 0140))
  560.                 _bttyout (c);
  561.             else if (eflag > 1)
  562.                 _bttyout (c);
  563.  
  564.             goto startover;
  565.  
  566.         case ZPAD | 0200:                /* This is what we want.            */
  567.         case ZPAD:                        /* This is what we want.            */
  568.             break;
  569.         }    /* switch (c = _readline (_Rxtimeout)) */
  570.         
  571.     cancount = 5;
  572.  
  573. splat:
  574.     switch (c = noxrd7 ())
  575.         {
  576.         case ZPAD:
  577.             goto splat;
  578.  
  579.         case RCDO:
  580.         case ZTIMEOUT:
  581.             goto fifi;
  582.  
  583.         default:
  584.             goto agn2;
  585.  
  586.         case ZDLE:                        /* This is what we want.             */
  587.             break;
  588.         }    /* switch (c = noxrd7 ()) */
  589.  
  590.     switch (c = noxrd7 ())
  591.         {
  592.         case RCDO:
  593.         case ZTIMEOUT:
  594.             goto fifi;
  595.  
  596.         case ZBIN:
  597.             Rxframeind = ZBIN;
  598.             _Crc32 = FALSE;
  599.             c = zrbhdr (hdr);
  600.             break;
  601.  
  602.         case ZBIN32:
  603.             _Crc32 = Rxframeind = ZBIN32;
  604.             c = zrbhdr32 (hdr);
  605.             break;
  606.  
  607.         case ZHEX:
  608.             Rxframeind = ZHEX;
  609.             _Crc32 = FALSE;
  610.             c = zrhhdr (hdr);
  611.             break;
  612.  
  613.         case CAN:
  614.             goto gotcan;
  615.  
  616.         default:
  617.             goto agn2;
  618.         }    /* switch (c = noxrd7 ()) */
  619.         
  620.     _Rxpos = hdr[ZP3] & 0377;
  621.     _Rxpos = (_Rxpos << 8) + (hdr[ZP2] & 0377);
  622.     _Rxpos = (_Rxpos << 8) + (hdr[ZP1] & 0377);
  623.     _Rxpos = (_Rxpos << 8) + (hdr[ZP0] & 0377);
  624.  
  625. fifi:
  626.     switch (c)
  627.         {
  628.         case GOTCAN:
  629.             c = ZCAN;
  630.  
  631.             /* **** FALL THRU TO **** */
  632.  
  633.         case ZNAK:
  634.         case ZCAN:
  635.         case ERROR:
  636.         case ZTIMEOUT:
  637.         case RCDO:
  638.             _zperr_ ("Got %s", frametypes[c + FTOFFSET]);
  639.  
  640.             /* **** FALL THRU TO **** */
  641.  
  642.         default:
  643.             if (c >= -3 && c <= FRTYPES)
  644.                 _vfile ("_zgethdr: %s %lx", frametypes[c + FTOFFSET], _Rxpos);
  645.             else
  646.                 _vfile ("_zgethdr: %d %lx", c, _Rxpos);
  647.  
  648.         }    /* switch (c) */
  649.         
  650.     return c;
  651.     }    /* int _zgethdr (char *hdr, int eflag) */
  652.  
  653.  
  654. /****************************************************************************
  655. *    zrbhdr                                                                    *
  656. *    Receive a binary style header (type and position).                        *
  657. ****************************************************************************/
  658.  
  659. static int zrbhdr (char *hdr)
  660.     {
  661.     int c, n;
  662.     unsigned short crc;
  663.  
  664.     if ((c = zdlread ()) & ~0377)
  665.         return c;
  666.  
  667.     Rxtype = c;
  668.     crc = updcrc (c, 0);
  669.  
  670.     for (n = 4; --n >= 0; ++hdr)
  671.         {
  672.         if ((c = zdlread ()) & ~0377)
  673.             return c;
  674.  
  675.         crc = updcrc (c, crc);
  676.         *hdr = (char) c;
  677.         }
  678.  
  679.     if ((c = zdlread ()) & ~0377)
  680.         return c;
  681.  
  682.     crc = updcrc (c, crc);
  683.     if ((c = zdlread ()) & ~0377)
  684.         return c;
  685.  
  686.     crc = updcrc (c, crc);
  687.     if (crc & 0xFFFF)
  688.         {
  689.         _zperr_ ("Bad Header CRC");
  690.         return ERROR;
  691.         }
  692.  
  693.     _Zmodem = 1;
  694.     return Rxtype;
  695.     }    /* static int zrbhdr (char *hdr) */
  696.     
  697.  
  698. /****************************************************************************
  699. *    zrbhdr32                                                                *
  700. *    Receive a binary style header (type and position) with 32 bit FCS.        *
  701. ****************************************************************************/
  702.  
  703. static int zrbhdr32 (char *hdr)
  704.     {
  705.     int c, n;
  706.     UNSL long crc;
  707.  
  708.     if ((c = zdlread ()) & ~0377)
  709.         return c;
  710.  
  711.     Rxtype = c;
  712.     crc = 0xFFFFFFFFL;
  713.     crc = UPDC32 (c, crc);
  714. #ifdef DEBUGZ
  715.     _vfile ("zrbhdr32 c=%X  crc=%lX", c, crc);
  716. #endif
  717.  
  718.     for (n = 4; --n >= 0; ++hdr)
  719.         {
  720.         if ((c = zdlread ()) & ~0377)
  721.             return c;
  722.  
  723.         crc = UPDC32 (c, crc);
  724.         *hdr = (char) c;
  725. #ifdef DEBUGZ
  726.         _vfile ("zrbhdr32 c=%X  crc=%lX", c, crc);
  727. #endif
  728.         }
  729.  
  730.     for (n = 4; --n >= 0;)
  731.         {
  732.         if ((c = zdlread ()) & ~0377)
  733.             return c;
  734.  
  735.         crc = UPDC32 (c, crc);
  736. #ifdef DEBUGZ
  737.         _vfile ("zrbhdr32 c=%X  crc=%lX", c, crc);
  738. #endif
  739.         }
  740.  
  741.     if (crc != 0xDEBB20E3L)
  742.         {
  743.         _zperr_ ("Bad Header CRC"); return ERROR;
  744.         }
  745.  
  746.     _Zmodem = 1;
  747.     return Rxtype;
  748.     }    /* static int zrbhdr32 (char *hdr) */
  749.     
  750.  
  751. /****************************************************************************
  752. *    zrhhdr                                                                    *
  753. *    Receive a hex style header (type and position).                            *
  754. ****************************************************************************/
  755.  
  756. static int zrhhdr (char *hdr)
  757.     {
  758.     int c;
  759.     unsigned short crc;
  760.     int n;
  761.  
  762.     if ((c = zgethex ()) < 0)
  763.         return c;
  764.  
  765.     Rxtype = c;
  766.     crc = updcrc (c, 0);
  767.  
  768.     for (n = 4; --n >= 0; ++hdr)
  769.         {
  770.         if ((c = zgethex ()) < 0)
  771.             return c;
  772.             
  773.         crc = updcrc (c, crc);
  774.         *hdr = (char) c;
  775.         }
  776.  
  777.     if ((c = zgethex ()) < 0)
  778.         return c;
  779.  
  780.     crc = updcrc (c, crc);
  781.     if ((c = zgethex ()) < 0)
  782.         return c;
  783.  
  784.     crc = updcrc (c, crc);
  785.     if (crc & 0xFFFF)
  786.         {
  787.         _zperr_ ("Bad Header CRC");
  788.         return ERROR;
  789.         }
  790.  
  791.     if (_readline (1) == '\r')            /* Throw away possible cr/lf         */
  792.         _readline (1);
  793.         
  794.     _Zmodem = 1;
  795.     return Rxtype;
  796.     }    /* static int zrhhdr (char *hdr) */
  797.     
  798.  
  799. /****************************************************************************
  800. *    zputhex                                                                    *
  801. *    Send a byte as two hex digits.                                            *
  802. ****************************************************************************/
  803.  
  804. static void zputhex (int c)
  805.     {
  806.     static char    digits[] = "0123456789abcdef";
  807.  
  808.     if (_Verbose > 8)
  809.         _vfile ("zputhex: %02X", c);
  810.         
  811.     _sendline (digits[(c & 0xF0) >> 4]);
  812.     _sendline (digits[(c) & 0xF]);
  813.     }    /* static void zputhex (int c) */
  814.     
  815.  
  816. /****************************************************************************
  817. *    zsendline                                                                *
  818. *    Send character <c> with ZMODEM escape sequence encoding.  Escape XON,    *
  819. *    XOFF.  Escape CR following @ (Telenet net escape).                        *
  820. ****************************************************************************/
  821.  
  822. static void zsendline (int c)
  823.     {
  824.     static int lastsent;
  825.  
  826.     switch (c &= 0377)
  827.         {
  828.         case ZDLE:
  829.             _xsendline (ZDLE);
  830.             _xsendline (lastsent = (c ^= 0100));
  831.             break;
  832.  
  833.         case 015:
  834.         case 0215:
  835.             if (!_Zctlesc && (lastsent & 0177) != '@')
  836.                 goto sendit;
  837.  
  838.             /* **** FALL THRU TO **** */
  839.  
  840.         case 020:
  841.         case 021:
  842.         case 023:
  843.         case 0220:
  844.         case 0221:
  845.         case 0223:
  846.             _xsendline (ZDLE);
  847.             c ^= 0100;
  848.  
  849. sendit:
  850.             _xsendline (lastsent = c);
  851.             break;
  852.  
  853.         default:
  854.             if (_Zctlesc && ! (c & 0140))
  855.                 {
  856.                 _xsendline (ZDLE);
  857.                 c ^= 0100;
  858.                 }
  859.  
  860.             _xsendline (lastsent = c);
  861.         }    /* switch (c &= 0377) */
  862.         
  863.     }    /* static void zsendline (int c) */
  864.     
  865.  
  866. /****************************************************************************
  867. *    zgethex, zgeth1                                                            *
  868. *    Decode two lower case hex digits into an 8 bit byte value.                *
  869. ****************************************************************************/
  870.  
  871. static int zgethex (void)
  872.     {
  873.     int c;
  874.  
  875.     c = zgeth1 ();
  876.     if (_Verbose > 8)
  877.         _vfile ("zgethex: %02X", c);
  878.  
  879.     return c;
  880.     }    /* static int zgethex (void) */
  881.     
  882. static int zgeth1 (void)
  883.     {
  884.     int c, n;
  885.  
  886.     if ((c = noxrd7 ()) < 0)
  887.         return c;
  888.  
  889.     n = c - '0';
  890.     if (n > 9)
  891.         n -= ('a' - ':');
  892.  
  893.     if (n & ~0xF)
  894.         return ERROR;
  895.  
  896.     if ((c = noxrd7 ()) < 0)
  897.         return c;
  898.  
  899.     c -= '0';
  900.     if (c > 9)
  901.         c -= ('a' - ':');
  902.  
  903.     if (c & ~0xF)
  904.         return ERROR;
  905.  
  906.     c += (n << 4);
  907.     return c;
  908.     }    /* static int zgeth1 (void) */
  909.     
  910.  
  911. /****************************************************************************
  912. *    zdlread                                                                    *
  913. *    Read a byte, checking for ZMODEM escape encoding including CAN * 5        *
  914. *    which represents a quick abort.                                            *
  915. ****************************************************************************/
  916.  
  917. static int zdlread (void)
  918.     {
  919.     int c;
  920.  
  921. again:
  922.     switch (c = _readline (_Rxtimeout))
  923.         {
  924.         case ZDLE:
  925.             break;
  926.  
  927.         case 023:
  928.         case 0223:
  929.         case 021:
  930.         case 0221:
  931.             goto again;
  932.  
  933.         default:
  934.             if (_Zctlesc && !(c & 0140))
  935.                 {
  936.                 goto again;
  937.                 }
  938.  
  939.             return c;
  940.         }    /* switch (c = _readline (_Rxtimeout)) */
  941.         
  942. again2:
  943.     if ((c = _readline (_Rxtimeout)) < 0)
  944.         return c;
  945.  
  946.     if (c == CAN && (c = _readline (_Rxtimeout)) < 0)
  947.         return c;
  948.  
  949.     if (c == CAN && (c = _readline (_Rxtimeout)) < 0)
  950.         return c;
  951.  
  952.     if (c == CAN && (c = _readline (_Rxtimeout)) < 0)
  953.         return c;
  954.  
  955.     switch (c)
  956.         {
  957.         case CAN:
  958.             return GOTCAN;
  959.  
  960.         case ZCRCE:
  961.         case ZCRCG:
  962.         case ZCRCQ:
  963.         case ZCRCW:
  964.             return (c | GOTOR);
  965.  
  966.         case ZRUB0:
  967.             return 0177;
  968.  
  969.         case ZRUB1:
  970.             return 0377;
  971.  
  972.         case 023:
  973.         case 0223:
  974.         case 021:
  975.         case 0221:
  976.             goto again2;
  977.  
  978.         default:
  979.             if (_Zctlesc && ! (c & 0140))
  980.                 {
  981.                 goto again2;
  982.                 }
  983.  
  984.             if ((c & 0140) ==  0100)
  985.                 return (c ^ 0100);
  986.  
  987.             break;
  988.         }    /* switch (c) */
  989.         
  990.     _zperr_ ("Bad escape sequence %x", c);
  991.     return ERROR;
  992.     }    /* static int zdlread (void) */
  993.  
  994.     
  995. /****************************************************************************
  996. *    noxrd7                                                                    *
  997. *    Read a character from the modem line with timeout.  Eat parity, XON     *
  998. *    and XOFF characters.                                                    *
  999. ****************************************************************************/
  1000.  
  1001. static int noxrd7 (void)
  1002.     {
  1003.     int c;
  1004.  
  1005.     for (;;)
  1006.         {
  1007.         if ((c = _readline (_Rxtimeout)) < 0)
  1008.             return c;
  1009.  
  1010.         switch (c &= 0177)
  1011.             {
  1012.             case XON:
  1013.             case XOFF:
  1014.                 continue;
  1015.  
  1016.             default:
  1017.                 if (_Zctlesc && !(c & 0140))
  1018.                     continue;
  1019.  
  1020.             case '\r':
  1021.             case '\n':
  1022.             case ZDLE:
  1023.                 return c;
  1024.             }    /* switch (c &= 0177) */
  1025.             
  1026.         }    /* for (;;) */
  1027.         
  1028.     }    /* static int noxrd7 (void) */
  1029.     
  1030.  
  1031. /****************************************************************************
  1032. *    _stohdr                                                                    *
  1033. *    Store long integer pos in _Txhdr.                                        *
  1034. ****************************************************************************/
  1035.  
  1036. void _stohdr (long pos)
  1037.     {
  1038.     _Txhdr[ZP0] = (char) pos;
  1039.     _Txhdr[ZP1] = (char) (pos >> 8);
  1040.     _Txhdr[ZP2] = (char) (pos >> 16);
  1041.     _Txhdr[ZP3] = (char) (pos >> 24);
  1042.     }    /* void _stohdr (long pos) */
  1043.     
  1044.  
  1045. /****************************************************************************
  1046. *    _rclhdr                                                                    *
  1047. *    Recover a long integer from a header.                                    *
  1048. ****************************************************************************/
  1049.  
  1050. long _rclhdr (char *hdr)
  1051.     {
  1052.     long l;
  1053.  
  1054.     l = (hdr[ZP3] & 0377);
  1055.     l = (l << 8) | (hdr[ZP2] & 0377);
  1056.     l = (l << 8) | (hdr[ZP1] & 0377);
  1057.     l = (l << 8) | (hdr[ZP0] & 0377);
  1058.     return l;
  1059.     }    /* long _rclhdr (char *hdr) */
  1060.  
  1061. /* End of zm.c */
  1062.