home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / rzsz_3_36_3_src.lzh / zm.c < prev    next >
Text File  |  1996-01-08  |  20KB  |  1,022 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. #ifdef OS9
  52. #define ZM_C
  53. #include <stdio.h>
  54. #include "os9.h"
  55. /* from rbsb.c */
  56. extern FILE *Ttystream;
  57. extern int Verbose;
  58. /* from rz.c */
  59. extern unsigned Effbaud;
  60. extern int Zctlesc;
  61. extern int Zmodem;
  62. extern int Zrwindow;
  63. /* from crctab.c */
  64. long UPDC32();
  65.  
  66. #ifdef m6809
  67. unsigned updcrc();
  68. #else /* !m6809 */
  69. unsigned long updcrc();
  70. #endif /* !m6809 */
  71.  
  72. /* from zmr.c */
  73. int zrdatr32();
  74. #endif /* OS9 */
  75.  
  76.  
  77. #ifndef CANFDX
  78. #include "zmodem.h"
  79. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  80. #endif
  81.  
  82. /* Globals used by ZMODEM functions */
  83. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  84. int Rxtype;        /* Type of header received */
  85. int Rxhlen;        /* Length of header received */
  86. int Rxcount;        /* Count of data bytes received */
  87. char Rxhdr[ZMAXHLEN];    /* Received header */
  88. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  89. long Rxpos;        /* Received file position */
  90. long Txpos;        /* Transmitted file position */
  91. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  92. int Crc32t;        /* Controls 32 bit CRC being sent */
  93.             /* 1 == CRC32,  2 == CRC32 + RLE */
  94. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  95.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  96. int Usevhdrs;        /* Use variable length headers */
  97. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  98. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  99. char *Altcan;        /* Alternate canit string */
  100.  
  101. static lastsent;    /* Last char we sent */
  102.  
  103. #ifdef OS9
  104. char *frametypes[] = {
  105. #else
  106. static char *frametypes[] = {
  107. #endif
  108.     "No Response to Error Correction Request",    /* -4 */
  109.     "No Carrier Detect",        /* -3 */
  110.     "TIMEOUT",        /* -2 */
  111.     "ERROR",        /* -1 */
  112. #define FTOFFSET 4
  113.     "ZRQINIT",
  114.     "ZRINIT",
  115.     "ZSINIT",
  116.     "ZACK",
  117.     "ZFILE",
  118.     "ZSKIP",
  119.     "ZNAK",
  120.     "ZABORT",
  121.     "ZFIN",
  122.     "ZRPOS",
  123.     "ZDATA",
  124.     "ZEOF",
  125.     "ZFERR",
  126.     "ZCRC",
  127.     "ZCHALLENGE",
  128.     "ZCOMPL",
  129.     "ZCAN",
  130.     "ZFREECNT",
  131.     "ZCOMMAND",
  132.     "ZSTDERR",
  133.     "xxxxx"
  134. #define FRTYPES 22    /* Total number of frame types in this array */
  135.             /*  not including psuedo negative entries */
  136. };
  137.  
  138. #ifdef OS9
  139. char badcrc[] = "Bad CRC";
  140. #else
  141. static char badcrc[] = "Bad CRC";
  142. #endif
  143.  
  144. /* Send ZMODEM binary header hdr of type type */
  145. zsbhdr(len, type, hdr)
  146. register char *hdr;
  147. {
  148. #ifdef m6809
  149.     int
  150. #else
  151.     register int
  152. #endif
  153.      n;
  154. #ifdef m6809
  155.     unsigned crc;
  156. #else
  157.     register unsigned short crc;
  158. #endif
  159.  
  160. #ifndef DSZ
  161.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  162.       frametypes[type+FTOFFSET], rclhdr(hdr));
  163. #endif
  164.     if (type == ZDATA)
  165.         for (n = Znulls; --n >=0; )
  166.             xsendline(0);
  167.  
  168.     xsendline(ZPAD); xsendline(ZDLE);
  169.  
  170.     switch (Crc32t=Txfcs32) {
  171.     case 2:
  172.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  173.         flushmo();  break;
  174.     case 1:
  175.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  176.     default:
  177.         if (Usevhdrs) {
  178.             xsendline(ZVBIN);
  179.             zsendline(len);
  180.         }
  181.         else
  182.             xsendline(ZBIN);
  183.         zsendline(type);
  184.         crc = updcrc(type, 0);
  185.  
  186.         for (n=len; --n >= 0; ++hdr) {
  187.             zsendline(*hdr);
  188.             crc = updcrc((0377& *hdr), crc);
  189.         }
  190.         crc = updcrc(0,updcrc(0,crc));
  191.         zsendline(crc>>8);
  192.         zsendline(crc);
  193.     }
  194.     if (type != ZDATA)
  195.         flushmo();
  196. }
  197.  
  198.  
  199. /* Send ZMODEM binary header hdr of type type */
  200. zsbh32(len, hdr, type, flavour)
  201. register char *hdr;
  202. {
  203. #ifdef m6809
  204.     int n;
  205. #else
  206.     register int n;
  207. #endif
  208. #ifdef m6809
  209.     long crc;
  210. #else
  211.     register unsigned long crc;
  212. #endif
  213.  
  214.     xsendline(flavour); 
  215.     if (Usevhdrs) 
  216.         zsendline(len);
  217.     zsendline(type);
  218.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  219.  
  220.     for (n=len; --n >= 0; ++hdr) {
  221.         crc = UPDC32((0377 & *hdr), crc);
  222.         zsendline(*hdr);
  223.     }
  224.     crc = ~crc;
  225.     for (n=4; --n >= 0;) {
  226.         zsendline((int)crc);
  227.         crc >>= 8;
  228.     }
  229. }
  230.  
  231. /* Send ZMODEM HEX header hdr of type type */
  232. zshhdr(len, type, hdr)
  233. register char *hdr;
  234. {
  235. #ifdef m6809
  236.     int n;
  237. #else
  238.     register int n;
  239. #endif
  240. #ifdef m6809
  241.     unsigned crc;
  242. #else
  243.     register unsigned short crc;
  244. #endif
  245.  
  246. #ifndef DSZ
  247.     vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  248.       frametypes[type+FTOFFSET], rclhdr(hdr));
  249. #endif
  250.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  251.     if (Usevhdrs) {
  252.         sendline(ZVHEX);
  253.         zputhex(len);
  254.     }
  255.     else
  256.         sendline(ZHEX);
  257.     zputhex(type);
  258.     Crc32t = 0;
  259.  
  260.     crc = updcrc(type, 0);
  261.     for (n=len; --n >= 0; ++hdr) {
  262.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  263.     }
  264.     crc = updcrc(0,updcrc(0,crc));
  265.     zputhex(crc>>8); zputhex(crc);
  266.  
  267.     /* Make it printable on remote machine */
  268.     sendline(015); sendline(0212);
  269.     /*
  270.      * Uncork the remote in case a fake XOFF has stopped data flow
  271.      */
  272.     if (type != ZFIN && type != ZACK)
  273.         sendline(021);
  274.     flushmo();
  275. }
  276.  
  277. /*
  278.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  279.  */
  280. #ifdef OS9
  281. char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  282. #else
  283. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  284. #endif
  285.  
  286. zsdata(buf, length, frameend)
  287. register char *buf;
  288. {
  289. #ifdef m6809
  290.     unsigned crc;
  291. #else
  292.     register unsigned short crc;
  293. #endif
  294. #ifndef DSZ
  295.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  296. #endif
  297.     switch (Crc32t) {
  298.     case 1:
  299.         zsda32(buf, length, frameend);  break;
  300.     case 2:
  301.         zsdar32(buf, length, frameend);  break;
  302.     default:
  303.         crc = 0;
  304.         for (;--length >= 0; ++buf) {
  305.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  306.         }
  307.         xsendline(ZDLE); xsendline(frameend);
  308.         crc = updcrc(frameend, crc);
  309.  
  310.         crc = updcrc(0,updcrc(0,crc));
  311.         zsendline(crc>>8); zsendline(crc);
  312.     }
  313.     if (frameend == ZCRCW)
  314.         xsendline(XON);
  315.     if (frameend != ZCRCG)
  316.         flushmo();
  317. }
  318.  
  319. zsda32(buf, length, frameend)
  320. register char *buf;
  321. {
  322. #ifdef m6809
  323.     int c;
  324. #else
  325.     register int c;
  326. #endif
  327. #ifdef m6809
  328.     long crc;
  329. #else
  330.     register unsigned long crc;
  331. #endif
  332.  
  333.     crc = 0xFFFFFFFFL;
  334.     for (;--length >= 0; ++buf) {
  335.         c = *buf & 0377;
  336.         if (c & 0140)
  337.             xsendline(lastsent = c);
  338.         else
  339.             zsendline(c);
  340.         crc = UPDC32(c, crc);
  341.     }
  342.     xsendline(ZDLE); xsendline(frameend);
  343.     crc = UPDC32(frameend, crc);
  344.  
  345.     crc = ~crc;
  346.     for (c=4; --c >= 0;) {
  347.         zsendline((int)crc);  crc >>= 8;
  348.     }
  349. }
  350.  
  351. /*
  352.  * Receive array buf of max length with ending ZDLE sequence
  353.  *  and CRC.  Returns the ending character or error code.
  354.  *  NB: On errors may store length+1 bytes!
  355.  */
  356. zrdata(buf, length)
  357. register char *buf;
  358. {
  359. #ifdef m6809
  360.     int c;
  361. #else
  362.     register int c;
  363. #endif
  364. #ifdef m6809
  365.     unsigned crc;
  366. #else
  367.     register unsigned short crc;
  368. #endif
  369. #ifdef m6809
  370.     char *end;
  371. #else
  372.     register char *end;
  373. #endif
  374. #ifdef m6809
  375.     int d;
  376. #else
  377.     register int d;
  378. #endif
  379.  
  380.     switch (Crc32r) {
  381.     case 1:
  382.         return zrdat32(buf, length);
  383.     case 2:
  384.         return zrdatr32(buf, length);
  385.     }
  386.  
  387.     crc = Rxcount = 0;  end = buf + length;
  388.     while (buf <= end) {
  389.         if ((c = zdlread()) & ~0377) {
  390. crcfoo:
  391.             switch (c) {
  392.             case GOTCRCE:
  393.             case GOTCRCG:
  394.             case GOTCRCQ:
  395.             case GOTCRCW:
  396.                 crc = updcrc((d=c)&0377, crc);
  397.                 if ((c = zdlread()) & ~0377)
  398.                     goto crcfoo;
  399.                 crc = updcrc(c, crc);
  400.                 if ((c = zdlread()) & ~0377)
  401.                     goto crcfoo;
  402.                 crc = updcrc(c, crc);
  403.                 if (crc & 0xFFFF) {
  404.                     zperr(badcrc);
  405.                     return ERROR;
  406.                 }
  407.                 Rxcount = length - (end - buf);
  408. #ifndef DSZ
  409.                 vfile("zrdata: %d  %s", Rxcount,
  410.                  Zendnames[d-GOTCRCE&3]);
  411. #endif
  412.                 return d;
  413.             case GOTCAN:
  414.                 zperr("Sender Canceled");
  415.                 return ZCAN;
  416.             case TIMEOUT:
  417.                 zperr("TIMEOUT");
  418.                 return c;
  419.             default:
  420.                 garbitch(); return c;
  421.             }
  422.         }
  423.         *buf++ = c;
  424.         crc = updcrc(c, crc);
  425.     }
  426. #ifdef DSZ
  427.     garbitch(); 
  428. #else
  429.     zperr("Data subpacket too long");
  430. #endif
  431.     return ERROR;
  432. }
  433.  
  434. zrdat32(buf, length)
  435. register char *buf;
  436. {
  437. #ifdef m6809
  438.     int c;
  439. #else
  440.     register int c;
  441. #endif
  442. #ifdef m6809
  443.     long crc;
  444. #else
  445.     register unsigned long crc;
  446. #endif
  447. #ifdef m6809
  448.     char *end;
  449. #else
  450.     register char *end;
  451. #endif
  452. #ifdef m6809
  453.     int d;
  454. #else
  455.     register int d;
  456. #endif
  457.  
  458.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  459.     while (buf <= end) {
  460.         if ((c = zdlread()) & ~0377) {
  461. crcfoo:
  462.             switch (c) {
  463.             case GOTCRCE:
  464.             case GOTCRCG:
  465.             case GOTCRCQ:
  466.             case GOTCRCW:
  467.                 d = c;  c &= 0377;
  468.                 crc = UPDC32(c, crc);
  469.                 if ((c = zdlread()) & ~0377)
  470.                     goto crcfoo;
  471.                 crc = UPDC32(c, crc);
  472.                 if ((c = zdlread()) & ~0377)
  473.                     goto crcfoo;
  474.                 crc = UPDC32(c, crc);
  475.                 if ((c = zdlread()) & ~0377)
  476.                     goto crcfoo;
  477.                 crc = UPDC32(c, crc);
  478.                 if ((c = zdlread()) & ~0377)
  479.                     goto crcfoo;
  480.                 crc = UPDC32(c, crc);
  481.                 if (crc != 0xDEBB20E3) {
  482.                     zperr(badcrc);
  483.                     return ERROR;
  484.                 }
  485.                 Rxcount = length - (end - buf);
  486. #ifndef DSZ
  487.                 vfile("zrdat32: %d %s", Rxcount,
  488.                  Zendnames[d-GOTCRCE&3]);
  489. #endif
  490.                 return d;
  491.             case GOTCAN:
  492.                 zperr("Sender Canceled");
  493.                 return ZCAN;
  494.             case TIMEOUT:
  495.                 zperr("TIMEOUT");
  496.                 return c;
  497.             default:
  498.                 garbitch(); return c;
  499.             }
  500.         }
  501.         *buf++ = c;
  502.         crc = UPDC32(c, crc);
  503.     }
  504.     zperr("Data subpacket too long");
  505.     return ERROR;
  506. }
  507.  
  508. garbitch()
  509. {
  510.     zperr("Garbled data subpacket");
  511. }
  512.  
  513. /*
  514.  * Read a ZMODEM header to hdr, either binary or hex.
  515.  *
  516.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  517.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  518.  *   Otherwise return negative on error.
  519.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  520.  */
  521. zgethdr(hdr)
  522. char *hdr;
  523. {
  524. #ifdef m6809
  525.     int c, n, cancount;
  526. #else
  527.     register int c, n, cancount;
  528. #endif
  529.  
  530.     n = Zrwindow + Effbaud;        /* Max bytes before start of frame */
  531.     Rxframeind = Rxtype = 0;
  532.  
  533. startover:
  534.     cancount = 5;
  535. again:
  536.     /* Return immediate ERROR if ZCRCW sequence seen */
  537.     switch (c = readline(Rxtimeout)) {
  538.     case 021: case 0221:
  539.         goto again;
  540.     case RCDO:
  541.     case TIMEOUT:
  542.         goto fifi;
  543.     case CAN:
  544. gotcan:
  545.         if (--cancount <= 0) {
  546.             c = ZCAN; goto fifi;
  547.         }
  548.         switch (c = readline(Rxtimeout)) {
  549.         case TIMEOUT:
  550.             goto again;
  551.         case ZCRCW:
  552.             switch (readline(Rxtimeout)) {
  553.             case TIMEOUT:
  554.                 c = ERROR; goto fifi;
  555.             case RCDO:
  556.                 goto fifi;
  557.             default:
  558.                 goto agn2;
  559.             }
  560.         case RCDO:
  561.             goto fifi;
  562.         default:
  563.             break;
  564.         case CAN:
  565.             if (--cancount <= 0) {
  566.                 c = ZCAN; goto fifi;
  567.             }
  568.             goto again;
  569.         }
  570.     /* **** FALL THRU TO **** */
  571.     default:
  572. agn2:
  573.         if ( --n == 0) {
  574.             c = GCOUNT;  goto fifi;
  575.         }
  576.         goto startover;
  577.     case ZPAD:        /* This is what we want. */
  578.         break;
  579.     }
  580.     cancount = 5;
  581. splat:
  582.     switch (c = noxrd7()) {
  583.     case ZPAD:
  584.         goto splat;
  585.     case RCDO:
  586.     case TIMEOUT:
  587.         goto fifi;
  588.     default:
  589.         goto agn2;
  590.     case ZDLE:        /* This is what we want. */
  591.         break;
  592.     }
  593.  
  594.  
  595.     Rxhlen = 4;        /* Set default length */
  596.     Rxframeind = c = noxrd7();
  597.     switch (c) {
  598.     case ZVBIN32:
  599.         if ((Rxhlen = c = zdlread()) < 0)
  600.             goto fifi;
  601.         if (c > ZMAXHLEN)
  602.             goto agn2;
  603.         Crc32r = 1;  c = zrbhd32(hdr); break;
  604.     case ZBIN32:
  605.         if (Usevhdrs)
  606.             goto agn2;
  607.         Crc32r = 1;  c = zrbhd32(hdr); break;
  608.     case ZVBINR32:
  609.         if ((Rxhlen = c = zdlread()) < 0)
  610.             goto fifi;
  611.         if (c > ZMAXHLEN)
  612.             goto agn2;
  613.         Crc32r = 2;  c = zrbhd32(hdr); break;
  614.     case ZBINR32:
  615.         if (Usevhdrs)
  616.             goto agn2;
  617.         Crc32r = 2;  c = zrbhd32(hdr); break;
  618.     case RCDO:
  619.     case TIMEOUT:
  620.         goto fifi;
  621.     case ZVBIN:
  622.         if ((Rxhlen = c = zdlread()) < 0)
  623.             goto fifi;
  624.         if (c > ZMAXHLEN)
  625.             goto agn2;
  626.         Crc32r = 0;  c = zrbhdr(hdr); break;
  627.     case ZBIN:
  628.         if (Usevhdrs)
  629.             goto agn2;
  630.         Crc32r = 0;  c = zrbhdr(hdr); break;
  631.     case ZVHEX:
  632.         if ((Rxhlen = c = zgethex()) < 0)
  633.             goto fifi;
  634.         if (c > ZMAXHLEN)
  635.             goto agn2;
  636.         Crc32r = 0;  c = zrhhdr(hdr); break;
  637.     case ZHEX:
  638.         if (Usevhdrs)
  639.             goto agn2;
  640.         Crc32r = 0;  c = zrhhdr(hdr); break;
  641.     case CAN:
  642.         goto gotcan;
  643.     default:
  644.         goto agn2;
  645.     }
  646.     for (n = Rxhlen; ++n < ZMAXHLEN; )    /* Clear unused hdr bytes */
  647.         hdr[n] = 0;
  648.     Rxpos = hdr[ZP3] & 0377;
  649.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  650.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  651.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  652. fifi:
  653.     switch (c) {
  654.     case GOTCAN:
  655.         c = ZCAN;
  656.     /* **** FALL THRU TO **** */
  657.     case ZNAK:
  658.     case ZCAN:
  659.     case ERROR:
  660.     case TIMEOUT:
  661.     case RCDO:
  662.     case GCOUNT:
  663.         zperr("Got %s", frametypes[c+FTOFFSET]);
  664.     /* **** FALL THRU TO **** */
  665. #ifndef DSZ
  666.     default:
  667.         if (c >= -4 && c <= FRTYPES)
  668.             vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  669.               frametypes[c+FTOFFSET], Rxpos);
  670.         else
  671.             vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  672. #endif
  673.     }
  674.     /* Use variable length headers if we got one */
  675.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  676.         Usevhdrs = 1;
  677.     return c;
  678. }
  679.  
  680. /* Receive a binary style header (type and position) */
  681. zrbhdr(hdr) /* is this used only for 16 bit crc's? GH */
  682. register char *hdr;
  683. {
  684. #ifdef m6809
  685.     int c, n;
  686. #else
  687.     register int c, n;
  688. #endif
  689. #ifdef m6809
  690.     unsigned crc; /* since when is crc int sized? GH */
  691. #else
  692.     register unsigned short crc;
  693. #endif
  694.  
  695.     if ((c = zdlread()) & ~0377)
  696.         return c;
  697.     Rxtype = c;
  698.     crc = updcrc(c, 0);
  699.  
  700.     for (n=Rxhlen; --n >= 0; ++hdr) {
  701.         if ((c = zdlread()) & ~0377)
  702.             return c;
  703.         crc = updcrc(c, crc);
  704.         *hdr = c;
  705.     }
  706.     if ((c = zdlread()) & ~0377)
  707.         return c;
  708.     crc = updcrc(c, crc);
  709.     if ((c = zdlread()) & ~0377)
  710.         return c;
  711.     crc = updcrc(c, crc);
  712.     if (crc & 0xFFFF) {
  713.         zperr(badcrc);
  714.         return ERROR;
  715.     }
  716. #ifdef ZMODEM
  717.     Protocol = ZMODEM;
  718. #endif
  719.     Zmodem = 1;
  720.     return Rxtype;
  721. }
  722.  
  723. /* Receive a binary style header (type and position) with 32 bit FCS */
  724. zrbhd32(hdr)
  725. register char *hdr;
  726. {
  727. #ifdef m6809
  728.     int c, n;
  729. #else
  730.     register int c, n;
  731. #endif
  732. #ifdef m6809
  733.     long crc;
  734. #else
  735.     register unsigned long crc;
  736. #endif
  737.  
  738.     if ((c = zdlread()) & ~0377)
  739.         return c;
  740.     Rxtype = c;
  741.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  742. #ifdef DEBUGZ
  743.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  744. #endif
  745.  
  746.     for (n=Rxhlen; --n >= 0; ++hdr) {
  747.         if ((c = zdlread()) & ~0377)
  748.             return c;
  749.         crc = UPDC32(c, crc);
  750.         *hdr = c;
  751. #ifdef DEBUGZ
  752.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  753. #endif
  754.     }
  755.     for (n=4; --n >= 0;) {
  756.         if ((c = zdlread()) & ~0377)
  757.             return c;
  758.         crc = UPDC32(c, crc);
  759. #ifdef DEBUGZ
  760.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  761. #endif
  762.     }
  763.     if (crc != 0xDEBB20E3) {
  764.         zperr(badcrc);
  765.         return ERROR;
  766.     }
  767. #ifdef ZMODEM
  768.     Protocol = ZMODEM;
  769. #endif
  770.     Zmodem = 1;
  771.     return Rxtype;
  772. }
  773.  
  774.  
  775. /* Receive a hex style header (type and position) */
  776. zrhhdr(hdr)
  777. char *hdr;
  778. {
  779.     register int c;
  780. #ifdef m6809
  781.     unsigned crc;
  782. #else
  783.     register unsigned short crc;
  784. #endif
  785.     register int n;
  786.  
  787.     if ((c = zgethex()) < 0)
  788.         return c;
  789.     Rxtype = c;
  790.     crc = updcrc(c, 0);
  791.  
  792.     for (n=Rxhlen; --n >= 0; ++hdr) {
  793.         if ((c = zgethex()) < 0)
  794.             return c;
  795.         crc = updcrc(c, crc);
  796.         *hdr = c;
  797.     }
  798.     if ((c = zgethex()) < 0)
  799.         return c;
  800.     crc = updcrc(c, crc);
  801.     if ((c = zgethex()) < 0)
  802.         return c;
  803.     crc = updcrc(c, crc);
  804.     if (crc & 0xFFFF) {
  805.         zperr(badcrc); return ERROR;
  806.     }
  807.     c = readline(Rxtimeout);
  808.     if (c < 0)
  809.         return c;
  810.     c = readline(Rxtimeout);
  811. #ifdef ZMODEM
  812.     Protocol = ZMODEM;
  813. #endif
  814.     Zmodem = 1;
  815.     if (c < 0)
  816.         return c;
  817.     return Rxtype;
  818. }
  819.  
  820. /* Send a byte as two hex digits */
  821. zputhex(c)
  822. register int c;
  823. {
  824.     static char    digits[]    = "0123456789abcdef";
  825.  
  826. #ifdef DEBUGZ
  827.     if (Verbose>8)
  828.         vfile("zputhex: %02X", c);
  829. #endif
  830.     sendline(digits[(c&0xF0)>>4]);
  831.     sendline(digits[(c)&0xF]);
  832. }
  833.  
  834. /*
  835.  * Send character c with ZMODEM escape sequence encoding.
  836.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  837.  */
  838. zsendline(c)
  839. register c;
  840. {
  841.     /* Quick check for non control characters */
  842.     if (c & 0140) /* this looks redundant as zsda32 does it too GH */
  843.         xsendline(lastsent = c);
  844.     else {
  845.         switch (c &= 0377) {
  846.         case ZDLE:
  847.             xsendline(ZDLE);  xsendline (lastsent = (c ^= 0100));
  848.             break;
  849.         case 021: case 023:
  850.         case 0221: case 0223:
  851.             xsendline(ZDLE);  c ^= 0100;  xsendline(lastsent = c);
  852.             break;
  853.         default:
  854.             if (Zctlesc && ! (c & 0140)) {
  855.                 xsendline(ZDLE);  c ^= 0100;
  856.             }
  857.             xsendline(lastsent = c);
  858.         }
  859.     }
  860. }
  861.  
  862. /* Decode two lower case hex digits into an 8 bit byte value */
  863. zgethex()
  864. {
  865.     register int c;
  866.  
  867.     c = zgeth1();
  868. #ifdef DEBUGZ
  869.     if (Verbose>8)
  870.         vfile("zgethex: %02X", c);
  871. #endif
  872.     return c;
  873. }
  874. zgeth1()
  875. {
  876.     register int c, n;
  877.  
  878.     if ((c = noxrd7()) < 0)
  879.         return c;
  880.     n = c - '0';
  881.     if (n > 9)
  882.         n -= ('a' - ':');
  883.     if (n & ~0xF)
  884.         return ERROR;
  885.     if ((c = noxrd7()) < 0)
  886.         return c;
  887.     c -= '0';
  888.     if (c > 9)
  889.         c -= ('a' - ':');
  890.     if (c & ~0xF)
  891.         return ERROR;
  892.     c += (n<<4);
  893.     return c;
  894. }
  895.  
  896. /*
  897.  * Read a byte, checking for ZMODEM escape encoding
  898.  *  including CAN*5 which represents a quick abort
  899.  */
  900. zdlread()
  901. {
  902.     register int c;
  903.  
  904. again:
  905.     /* Quick check for non control characters */
  906.     if ((c = readline(Rxtimeout)) & 0140)
  907.         return c;
  908.     switch (c) {
  909.     case ZDLE:
  910.         break;
  911.     case 023:
  912.     case 0223:
  913.     case 021:
  914.     case 0221:
  915.         goto again;
  916.     default:
  917.         if (Zctlesc && !(c & 0140)) {
  918.             goto again;
  919.         }
  920.         return c;
  921.     }
  922. again2:
  923.     if ((c = readline(Rxtimeout)) < 0)
  924.         return c;
  925.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  926.         return c;
  927.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  928.         return c;
  929.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  930.         return c;
  931.     switch (c) {
  932.     case CAN:
  933.         return GOTCAN;
  934.     case ZCRCE:
  935.     case ZCRCG:
  936.     case ZCRCQ:
  937.     case ZCRCW:
  938.         return (c | GOTOR);
  939.     case ZRUB0:
  940.         return 0177;
  941.     case ZRUB1:
  942.         return 0377;
  943.     case 023:
  944.     case 0223:
  945.     case 021:
  946.     case 0221:
  947.         goto again2;
  948.     default:
  949.         if (Zctlesc && ! (c & 0140)) {
  950.             goto again2;
  951.         }
  952.         if ((c & 0140) ==  0100)
  953.             return (c ^ 0100);
  954.         break;
  955.     }
  956.     if (Verbose>1)
  957.         zperr("Bad escape sequence %x", c);
  958.     return ERROR;
  959. }
  960.  
  961. /*
  962.  * Read a character from the modem line with timeout.
  963.  *  Eat parity, XON and XOFF characters.
  964.  */
  965. noxrd7()
  966. {
  967.     register int c;
  968.  
  969.     for (;;) {
  970.         if ((c = readline(Rxtimeout)) < 0)
  971.             return c;
  972.         switch (c &= 0177) {
  973.         case XON:
  974.         case XOFF:
  975.             continue;
  976.         default:
  977.             if (Zctlesc && !(c & 0140))
  978.                 continue;
  979.         case '\r':
  980. #ifdef OS9
  981.         case '\l':
  982. #else
  983.         case '\n':
  984. #endif
  985.         case ZDLE:
  986.             return c;
  987.         }
  988.     }
  989.     /* NOTREACHED */
  990. }
  991.  
  992. /* Store long integer pos in Txhdr */
  993. stohdr(pos)
  994. long pos;
  995. {
  996.     Txhdr[ZP0] = pos;
  997.     Txhdr[ZP1] = pos>>8;
  998.     Txhdr[ZP2] = pos>>16;
  999.     Txhdr[ZP3] = pos>>24;
  1000. }
  1001.  
  1002. /* Recover a long integer from a header */
  1003. long
  1004. rclhdr(hdr)
  1005. register char *hdr;
  1006. {
  1007. #ifdef m6809
  1008.     long
  1009. #else
  1010.     register long
  1011. #endif
  1012.     L; /* this var was an l(el). try and define vs a 1(one) GH */
  1013.  
  1014.     L = (hdr[ZP3] & 0377);
  1015.     L = (L << 8) | (hdr[ZP2] & 0377);
  1016.     L = (L << 8) | (hdr[ZP1] & 0377);
  1017.     L = (L << 8) | (hdr[ZP0] & 0377);
  1018.     return L;
  1019. }
  1020.  
  1021. /* End of zm.c */
  1022.