home *** CD-ROM | disk | FTP | other *** search
/ HomeWare 14 / HOMEWARE14.bin / unix / rzsz0306.arj / ZM.C < prev    next >
C/C++ Source or Header  |  1994-01-27  |  18KB  |  882 lines

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