home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / HEATH / HMSRC20.LBR / HZM.CZ / HZM.C
Text File  |  2000-06-30  |  13KB  |  710 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    07-28-87  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) 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. #define  ZM
  17. #define  C80
  18.  
  19. #include "hmodem80.h"
  20. #include "zmodem.h"
  21.  
  22. long updc32();
  23.  
  24.  
  25. /* Send ZMODEM binary header hdr of type type */
  26. zsbhdr(type, hdr)
  27. char *hdr;
  28. {
  29.     static int n;
  30.     static unsigned crc;
  31.  
  32.     if (type == ZDATA)
  33.         for (n = Znulls; --n >=0; )
  34.             zsendline(0);
  35.  
  36.     mcharout(ZPAD); 
  37.     mcharout(ZDLE);
  38.  
  39.     if (Crc32t=Txfcs32)
  40.         zsbh32(hdr, type);
  41.     else {
  42.         mcharout(ZBIN); 
  43.         zsendline(type); 
  44.         crc = updcrc(type, 0);
  45.  
  46.         for (n=4; --n >= 0; ++hdr) {
  47.             zsendline(*hdr);
  48.             crc = updcrc((0377& *hdr), crc);
  49.         }
  50.         crc = updcrc(0,updcrc(0,crc));
  51.         zsendline(crc>>8);
  52.         zsendline(crc);
  53.     }
  54.     if (type != ZDATA)
  55.         purgeline();
  56. }
  57.  
  58.  
  59. /* Send ZMODEM binary header hdr of type type */
  60.  
  61. zsbh32(hdr, type)
  62. char *hdr;
  63. {
  64.     static int n;
  65.     static long crc;
  66.  
  67.     mcharout(ZBIN32);  
  68.     zsendline(type);
  69.     crc = 0xFFFFFFFFL; 
  70.     crc = updc32(type, crc);
  71.  
  72.     for (n=4; --n >= 0; ++hdr) {
  73.         crc = updc32((0377 & *hdr), crc);
  74.         zsendline(*hdr);
  75.     }
  76.     crc = ~crc;
  77.     for (n=4; --n >= 0;) {
  78.         zsendline((int)crc);
  79.         crc >>= 8;
  80.     }
  81. }
  82.  
  83. /* Send ZMODEM HEX header hdr of type type */
  84.  
  85. zshhdr(type, hdr)
  86. char *hdr;
  87. {
  88.     static int n;
  89.     static unsigned crc;
  90.  
  91.    mcharout(ZPAD); 
  92.    mcharout(ZPAD); 
  93.    mcharout(ZDLE); 
  94.    mcharout(ZHEX);
  95.     zputhex(type);
  96.     Crc32t = 0;
  97.  
  98.     crc = updcrc(type, 0);
  99.     for (n=4; --n >= 0; ++hdr) {
  100.         zputhex(*hdr); 
  101.         crc = updcrc((0377 & *hdr), crc);
  102.     }
  103.     crc = updcrc(0,updcrc(0,crc));
  104.     zputhex(crc>>8); 
  105.     zputhex(crc);
  106.  
  107.     /* Make it printable on remote machine */
  108.    mcharout(CR); 
  109.    mcharout(LF);
  110.     /*
  111.      * Uncork the remote in case a fake XOFF has stopped data flow
  112.      */
  113.     if (type != ZFIN && type != ZACK)
  114.        mcharout(CTRLQ);
  115.     purgeline();
  116. }
  117.  
  118. /*
  119.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  120.  */
  121. zsdata(buf, length, frameend)
  122. int length, frameend;
  123. char *buf;
  124. {
  125.     static unsigned crc;
  126.  
  127.     if (Crc32t)
  128.         zsda32(buf, length, frameend);
  129.     else {
  130.         crc = 0;
  131.         for (;--length >= 0; ++buf) {
  132.             zsendline(*buf); 
  133.             crc = updcrc((0377 & *buf), crc);
  134.         }
  135.         mcharout(ZDLE); 
  136.         mcharout(frameend);
  137.         crc = updcrc(frameend, crc);
  138.  
  139.         crc = updcrc(0,updcrc(0,crc));
  140.         zsendline(crc>>8); 
  141.         zsendline(crc);
  142.     }
  143.     if (frameend == ZCRCW) {
  144.         mcharout(XON);  
  145.         purgeline();
  146.     }
  147. }
  148.  
  149. zsda32(buf, length, frameend)
  150. char *buf;
  151. int length, frameend;
  152. {
  153.     static long crc;
  154.  
  155.     crc = 0xFFFFFFFFL;
  156.     for (;--length >= 0;++buf) {
  157.         crc = updc32((0377 & *buf), crc);
  158.         zsendline(*buf);
  159.     }
  160.     mcharout(ZDLE); 
  161.     mcharout(frameend);
  162.     crc = updc32(frameend, crc);
  163.  
  164.     crc = ~crc;
  165.     for (length=4; --length >= 0;) {
  166.         zsendline((int)crc);  
  167.         crc >>= 8;
  168.     }
  169. }
  170.  
  171. /*
  172.  * Receive array buf of max length with ending ZDLE sequence
  173.  *  and CRC.  Returns the ending character or error code.
  174.  *  NB: On errors may store length+1 bytes!
  175.  */
  176. zrdata(buf, length)
  177. char *buf;
  178. {
  179.     static int c;
  180.     static unsigned crc;
  181.     static char *end;
  182.     static int d;
  183.  
  184.     if (Rxframeind == ZBIN32)
  185.         return zrdat32(buf, length);
  186.  
  187.     crc = Rxcount = 0;  
  188.     end = buf + length;
  189.     while (buf <= end) {
  190.         if ((c = zdlread()) & ~0377) {
  191. crcfoo:
  192.             switch (c) {
  193.             case GOTCRCE:
  194.             case GOTCRCG:
  195.             case GOTCRCQ:
  196.             case GOTCRCW:
  197.                 crc = updcrc((d=c)&0377, crc);
  198.                 if ((c = zdlread()) & ~0377)
  199.                     goto crcfoo;
  200.                 crc = updcrc(c, crc);
  201.                 if ((c = zdlread()) & ~0377)
  202.                     goto crcfoo;
  203.                 crc = updcrc(c, crc);
  204.                 if (crc & 0xFFFF) {
  205.                     zperr("Bad data CRC",TRUE);
  206.                     return NERROR;
  207.                 }
  208.                 Rxcount = length - (end - buf);
  209.                 return d;
  210.             case GOTCAN:
  211.                 zperr("Sender CANceled",TRUE);
  212.                 return ZCAN;
  213.             case TIMEOUT:
  214.                 zperr("TIMEOUT",TRUE);
  215.                 return c;
  216.             default:
  217.                 zperr("Bad data subpkt",TRUE);
  218.                 return c;
  219.             }
  220.         }
  221.         *buf++ = c;
  222.         crc = updcrc(c, crc);
  223.     }
  224.     zperr("Subpkt too long",TRUE);
  225.     return NERROR;
  226. }
  227.  
  228. zrdat32(buf, length)
  229. char *buf;
  230. {
  231.     static int c, d;
  232.     static long crc;
  233.     static char *end;
  234.  
  235.     crc = 0xFFFFFFFFL;  
  236.     Rxcount = 0;  
  237.     end = buf + length;
  238.     while (buf <= end) {
  239.         if ((c = zdlread()) & ~0377) {
  240. crcfoo:
  241.             switch (c) {
  242.             case GOTCRCE:
  243.             case GOTCRCG:
  244.             case GOTCRCQ:
  245.             case GOTCRCW:
  246.                 d = c;  
  247.                 c &= 0377;
  248.                 crc = updc32(c, crc);
  249.                 if ((c = zdlread()) & ~0377)
  250.                     goto crcfoo;
  251.                 crc = updc32(c, crc);
  252.                 if ((c = zdlread()) & ~0377)
  253.                     goto crcfoo;
  254.                 crc = updc32(c, crc);
  255.                 if ((c = zdlread()) & ~0377)
  256.                     goto crcfoo;
  257.                 crc = updc32(c, crc);
  258.                 if ((c = zdlread()) & ~0377)
  259.                     goto crcfoo;
  260.                 crc = updc32(c, crc);
  261.                 if (crc != 0xDEBB20E3) {
  262.                     zperr("Bad data CRC",TRUE);
  263.                     return NERROR;
  264.                 }
  265.                 Rxcount = length - (end - buf);
  266.                 return d;
  267.             case GOTCAN:
  268.                 zperr("Sender CANceled",TRUE);
  269.                 return ZCAN;
  270.             case TIMEOUT:
  271.                 zperr("TIMEOUT",TRUE);
  272.                 return c;
  273.             default:
  274.                 zperr("Bad data subpkt",TRUE);
  275.                 return c;
  276.             }
  277.         }
  278.         *buf++ = c;
  279.         crc = updc32(c, crc);
  280.     }
  281.     zperr("Subpkt too long",TRUE);
  282.     return NERROR;
  283. }
  284.  
  285.  
  286. /*
  287.  * Read a ZMODEM header to hdr, either binary or hex.
  288.  *  eflag controls local display of non zmodem characters:
  289.  *    0:  no display
  290.  *    1:  display printing characters only
  291.  *    2:  display all non ZMODEM characters
  292.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  293.  *   Otherwise return negative on error.
  294.  *   Return NERROR instantly if ZCRCW sequence, for fast error recovery.
  295.  */
  296. zgethdr(hdr, eflag)
  297. char *hdr;
  298. int eflag;
  299. {
  300.     static int c, n, cancount;
  301.  
  302.     n = Zrwindow + Baudrate;       /* Max bytes before start of frame */
  303.     Rxframeind = Rxtype = 0;
  304.  
  305. startover:
  306.     cancount = 5;
  307. again:
  308.     /* Return immediate NERROR if ZCRCW sequence seen */
  309.     switch (c = readline(Rxtimeout)) {
  310.     case RCDO:
  311.     case TIMEOUT:
  312.         goto fifi;
  313.     case CAN:
  314. gotcan:
  315.         if (--cancount <= 0) {
  316.             c = ZCAN; 
  317.             goto fifi;
  318.         }
  319.         switch (c = readline(INTRATIME)) {
  320.         case TIMEOUT:
  321.             goto again;
  322.         case ZCRCW:
  323.             c = NERROR;
  324.             /* **** FALL THRU TO **** */
  325.         case RCDO:
  326.             goto fifi;
  327.         default:
  328.             break;
  329.         case CAN:
  330.             if (--cancount <= 0) {
  331.                 c = ZCAN; 
  332.                 goto fifi;
  333.             }
  334.             goto again;
  335.         }
  336.         /* **** FALL THRU TO **** */
  337.     default:
  338. agn2:
  339.         if ( --n == 0) {
  340.             zperr("Grbg ct exceeded",TRUE);
  341.             return(NERROR);
  342.         }
  343.         goto startover;
  344.     case ZPAD|0200:        /* This is what we want. */
  345.     case ZPAD:        /* This is what we want. */
  346.         break;
  347.     }
  348.     cancount = 5;
  349. splat:
  350.     switch (c = noxrd7()) {
  351.     case ZPAD:
  352.         goto splat;
  353.     case RCDO:
  354.     case TIMEOUT:
  355.         goto fifi;
  356.     default:
  357.         goto agn2;
  358.     case ZDLE:        /* This is what we want. */
  359.         break;
  360.     }
  361.  
  362.     switch (c = noxrd7()) {
  363.     case RCDO:
  364.     case TIMEOUT:
  365.         goto fifi;
  366.     case ZBIN:
  367.         Rxframeind = ZBIN;  
  368.         Crc32 = FALSE;
  369.         c =  zrbhdr(hdr);
  370.         break;
  371.     case ZBIN32:
  372.         Crc32 = Rxframeind = ZBIN32;
  373.         c =  zrb32hdr(hdr);
  374.         break;
  375.     case ZHEX:
  376.         Rxframeind = ZHEX;  
  377.         Crc32 = FALSE;
  378.         c =  zrhhdr(hdr);
  379.         break;
  380.     case CAN:
  381.         goto gotcan;
  382.     default:
  383.         goto agn2;
  384.     }
  385.     Rxpos = (unsigned)(hdr[ZP3] & 0377);
  386.     Rxpos = (Rxpos<<8) + (unsigned)(hdr[ZP2] & 0377);
  387.     Rxpos = (Rxpos<<8) + (unsigned)(hdr[ZP1] & 0377);
  388.     Rxpos = (Rxpos<<8) + (unsigned)(hdr[ZP0] & 0377);
  389. fifi:
  390.     switch (c) {
  391.     case GOTCAN:
  392.         c = ZCAN;
  393.         /* **** FALL THRU TO **** */
  394.     case ZNAK:
  395.     case ZCAN:
  396.     case NERROR:
  397.     case TIMEOUT:
  398.     case RCDO:
  399.       sprintf(Buf,"Got %s", frametypes[c+FTOFFSET]);
  400.         zperr(Buf,TRUE);
  401.         /* **** FALL THRU TO **** */
  402.     default:
  403.       break;
  404.     }
  405.     return c;
  406. }
  407.  
  408. /* Receive a binary style header (type and position) */
  409. zrbhdr(hdr)
  410. char *hdr;
  411. {
  412.     static int c, n;
  413.     static unsigned crc;
  414.  
  415.     if ((c = zdlread()) & ~0377)
  416.         return c;
  417.     Rxtype = c;
  418.     crc = updcrc(c, 0);
  419.  
  420.     for (n=4; --n >= 0; ++hdr) {
  421.         if ((c = zdlread()) & ~0377)
  422.             return c;
  423.         crc = updcrc(c, crc);
  424.         *hdr = c;
  425.     }
  426.     if ((c = zdlread()) & ~0377)
  427.         return c;
  428.     crc = updcrc(c, crc);
  429.     if ((c = zdlread()) & ~0377)
  430.         return c;
  431.     crc = updcrc(c, crc);
  432.     if (crc & 0xFFFF) {
  433.         zperr("Bad Header CRC",TRUE); 
  434.         return NERROR;
  435.     }
  436.     Zmodem = 1;
  437.     return Rxtype;
  438. }
  439.  
  440. /* Receive a binary style header (type and position) with 32 bit FCS */
  441. zrb32hdr(hdr)
  442. char *hdr;
  443. {
  444.     static int c, n;
  445.     static long crc;
  446.  
  447.     if ((c = zdlread()) & ~0377)
  448.         return c;
  449.     Rxtype = c;
  450.     crc = 0xFFFFFFFFL; 
  451.     crc = updc32(c, crc);
  452. #ifdef DEBUGZ
  453. #endif
  454.  
  455.     for (n=4; --n >= 0; ++hdr) {
  456.         if ((c = zdlread()) & ~0377)
  457.             return c;
  458.         crc = updc32(c, crc);
  459.         *hdr = c;
  460. #ifdef DEBUGZ
  461. #endif
  462.     }
  463.     for (n=4; --n >= 0;) {
  464.         if ((c = zdlread()) & ~0377)
  465.             return c;
  466.         crc = updc32(c, crc);
  467. #ifdef DEBUGZ
  468. #endif
  469.     }
  470.     if (crc != 0xDEBB20E3) {
  471.         zperr("Bad Header CRC",TRUE); 
  472.         return NERROR;
  473.     }
  474.     Zmodem = 1;
  475.     return Rxtype;
  476. }
  477.  
  478.  
  479. /* Receive a hex style header (type and position) */
  480. zrhhdr(hdr)
  481. char *hdr;
  482. {
  483.     static int c;
  484.     static unsigned crc;
  485.     static int n;
  486.  
  487.     if ((c = zgethex()) < 0)
  488.         return c;
  489.     Rxtype = c;
  490.     crc = updcrc(c, 0);
  491.  
  492.     for (n=4; --n >= 0; ++hdr) {
  493.         if ((c = zgethex()) < 0)
  494.             return c;
  495.         crc = updcrc(c, crc);
  496.         *hdr = c;
  497.     }
  498.     if ((c = zgethex()) < 0)
  499.         return c;
  500.     crc = updcrc(c, crc);
  501.     if ((c = zgethex()) < 0)
  502.         return c;
  503.     crc = updcrc(c, crc);
  504.     if (crc & 0xFFFF) {
  505.         zperr("Bad Header CRC",TRUE); 
  506.         return NERROR;
  507.     }
  508.     if (readline(INTRATIME) == '\r')    /* Throw away possible cr/lf */
  509.         readline(INTRATIME);
  510.     Zmodem = 1; 
  511.     return Rxtype;
  512. }
  513.  
  514. /* Send a byte as two hex digits */
  515. zputhex(c)
  516. int c;
  517. {
  518.     static char    digits[]    = "0123456789abcdef";
  519.  
  520.    mcharout(digits[(c&0xF0)>>4]);
  521.    mcharout(digits[(c)&0xF]);
  522. }
  523.  
  524. /*
  525.  * Send character c with ZMODEM escape sequence encoding.
  526.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  527.  */
  528. zsendline(c)
  529. int c;
  530. {
  531.     static lastsent;
  532.  
  533.     switch (c &= 0377) {
  534.     case ZDLE:
  535.         mcharout(ZDLE);
  536.         mcharout (lastsent = (c ^= 0100));
  537.         break;
  538.     case 015:
  539.     case 0215:
  540.         if (!Zctlesc && (lastsent & 0177) != '@')
  541.             goto sendit;
  542.         /* **** FALL THRU TO **** */
  543.     case 020:
  544.     case 021:
  545.     case 023:
  546.     case 0220:
  547.     case 0221:
  548.     case 0223:
  549.         mcharout(ZDLE);
  550.         c ^= 0100;
  551. sendit:
  552.         mcharout(lastsent = c);
  553.         break;
  554.     default:
  555.         if (Zctlesc && ! (c & 0140)) {
  556.             mcharout(ZDLE);
  557.             c ^= 0100;
  558.         }
  559.         mcharout(lastsent = c);
  560.     }
  561. }
  562.  
  563. /* Decode two lower case hex digits into an 8 bit byte value */
  564. zgethex()
  565. {
  566.     int c;
  567.  
  568.     c = zgeth1();
  569.     return c;
  570. }
  571. zgeth1()
  572. {
  573.     static int c, n;
  574.  
  575.     if ((c = noxrd7()) < 0)
  576.         return c;
  577.     n = c - '0';
  578.     if (n > 9)
  579.         n -= ('a' - ':');
  580.     if (n & ~0xF)
  581.         return NERROR;
  582.     if ((c = noxrd7()) < 0)
  583.         return c;
  584.     c -= '0';
  585.     if (c > 9)
  586.         c -= ('a' - ':');
  587.     if (c & ~0xF)
  588.         return NERROR;
  589.     c += (n<<4);
  590.     return c;
  591. }
  592.  
  593. /*
  594.  * Read a byte, checking for ZMODEM escape encoding
  595.  *  including CAN*5 which represents a quick abort
  596.  */
  597.  
  598. zdlread()
  599. {
  600.     static int c;
  601.  
  602. again:
  603.     switch (c = readline(Rxtimeout)) {
  604.     case ZDLE:
  605.         break;
  606.     case 023:
  607.     case 0223:
  608.     case 021:
  609.     case 0221:
  610.         goto again;
  611.     default:
  612.         if (Zctlesc && !(c & 0140)) {
  613.             goto again;
  614.         }
  615.         return c;
  616.     }
  617. again2:
  618.     if ((c = readline(Rxtimeout)) < 0)
  619.         return c;
  620.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  621.         return c;
  622.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  623.         return c;
  624.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  625.         return c;
  626.     switch (c) {
  627.     case CAN:
  628.         return GOTCAN;
  629.     case ZCRCE:
  630.     case ZCRCG:
  631.     case ZCRCQ:
  632.     case ZCRCW:
  633.         return (c | GOTOR);
  634.     case ZRUB0:
  635.         return 0177;
  636.     case ZRUB1:
  637.         return 0377;
  638.     case 023:
  639.     case 0223:
  640.     case 021:
  641.     case 0221:
  642.         goto again2;
  643.     default:
  644.         if (Zctlesc && ! (c & 0140)) {
  645.             goto again2;
  646.         }
  647.         if ((c & 0140) ==  0100)
  648.             return (c ^ 0100);
  649.         break;
  650.     }
  651.    sprintf(Buf,"Bad escape %x", c);
  652.     zperr(Buf,TRUE);
  653.     return NERROR;
  654. }
  655.  
  656. /*
  657.  * Read a character from the modem line with timeout.
  658.  *  Eat parity, XON and XOFF characters.
  659.  */
  660. noxrd7()
  661. {
  662.     static int c;
  663.  
  664.     for (;;) {
  665.         if ((c = readline(Rxtimeout)) < 0)
  666.             return c;
  667.         switch (c &= 0177) {
  668.         case XON:
  669.         case XOFF:
  670.             continue;
  671.         default:
  672.             if (Zctlesc && !(c & 0140))
  673.                 continue;
  674.         case '\r':
  675.         case '\n':
  676.         case ZDLE:
  677.             return c;
  678.         }
  679.     }
  680. }
  681.  
  682. /* Store long integer pos in Txhdr */
  683. stohdr(pos)
  684. long pos;
  685. {
  686.     Txhdr[ZP0] = pos;
  687.     Txhdr[ZP1] = (pos>>8);
  688.     Txhdr[ZP2] = (pos>>16);
  689.     Txhdr[ZP3] = (pos>>24);
  690. }
  691.  
  692. /* Recover a long integer from a header */
  693. long
  694. rclhdr(hdr)
  695. char *hdr;
  696. {
  697.     static long l;
  698.  
  699.     l = (unsigned)(hdr[ZP3] & 0377);
  700.     l = (l << 8) | (unsigned)(hdr[ZP2] & 0377);
  701.     l = (l << 8) | (unsigned)(hdr[ZP1] & 0377);
  702.     l = (l << 8) | (unsigned)(hdr[ZP0] & 0377);
  703. #ifdef DEBUG
  704.    lreport(FBLOCKS,l);
  705. #endif
  706.     return l;
  707. }
  708.  
  709. /***************************** End of zm.c *********************************/
  710.