home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / telecomm / misc / xprzmodem.lha / Source / zm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-09  |  25.0 KB  |  936 lines

  1. /**********************************************************************
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    01-19-87  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * 29 July 89:
  7.  * Major overhaul by Rick Huebner for adaptation to Amiga XPR protocol spec
  8.  *
  9.  * 28 October 89:
  10.  * Converted to Lattice C 5.04
  11.  *
  12.  * 15 November 1991
  13.  * Code added to support CRC-32 by William M. Perkins.
  14.  *
  15.  * 28 June 1993
  16.  * Added run-length encoding code from original ZModem sources.
  17.  **********************************************************************/
  18.  
  19. /* Fast table-driven CRC functions for ZMODEM
  20.  * extracted from RBSB.C by Chuck Forsberg, Omen Technology, Inc.
  21.  *
  22.  * crctab calculated by Mark G. Mendel, Network Systems Corporation
  23.  */
  24.  
  25. static unsigned short crctab[256] =
  26. {
  27.   0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  28.   0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  29.   0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  30.   0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  31.   0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  32.   0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  33.   0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  34.   0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  35.   0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  36.   0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  37.   0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  38.   0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  39.   0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  40.   0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  41.   0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  42.   0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  43.   0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  44.   0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  45.   0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  46.   0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  47.   0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  48.   0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  49.   0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  50.   0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  51.   0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  52.   0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  53.   0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  54.   0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  55.   0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  56.   0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  57.   0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  58.   0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  59. };
  60.  
  61. /*
  62.  * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.
  63.  *  NOTE: First srgument must be in range 0 to 255.
  64.  *        Second argument is referenced twice.
  65.  *
  66.  * Programmers may incorporate any or all code into their programs,
  67.  * giving proper credit within the source. Publication of the
  68.  * source routines is permitted so long as proper credit is given
  69.  * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
  70.  * Omen Technology.
  71.  */
  72.  
  73. #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
  74.  
  75. /*
  76.  * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
  77.  * code or tables extracted from it, as desired without restriction.
  78.  */
  79.  
  80. /*
  81.  * First, the polynomial itself and its table of feedback terms.  The
  82.  * polynomial is
  83.  * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
  84.  * Note that we take it "backwards" and put the highest-order term in
  85.  * the lowest-order bit.  The X^32 term is "implied"; the LSB is the
  86.  * X^31 term, etc.  The X^0 term (usually shown as "+1") results in
  87.  * the MSB being 1.
  88.  *
  89.  * Note that the usual hardware shift register implementation, which
  90.  * is what we're using (we're merely optimizing it by doing eight-bit
  91.  * chunks at a time) shifts bits into the lowest-order term.  In our
  92.  * implementation, that means shifting towards the right.  Why do we
  93.  * do it this way?  Because the calculated CRC must be transmitted in
  94.  * order from highest-order term to lowest-order term.  UARTs transmit
  95.  * characters in order from LSB to MSB.  By storing the CRC this way,
  96.  * we hand it to the UART in the order low-byte to high-byte; the UART
  97.  * sends each low-bit to hight-bit; and the result is transmission bit
  98.  * by bit from highest- to lowest-order term without requiring any bit
  99.  * shuffling on our part.  Reception works similarly.
  100.  */
  101.  
  102. /*
  103.  * The feedback terms table consists of 256, 32-bit entries.  Notes:
  104.  *
  105.  *     The table can be generated at runtime if desired; code to do so
  106.  *     is shown later.  It might not be obvious, but the feedback
  107.  *     terms simply represent the results of eight shift/xor opera-
  108.  *     tions for all combinations of data and CRC register values.
  109.  *
  110.  *     The values must be right-shifted by eight bits by the "updcrc"
  111.  *     logic; the shift must be unsigned (bring in zeroes).  On some
  112.  *     hardware you could probably optimize the shift in assembler by
  113.  *     using byte-swap instructions.
  114.  */
  115.  
  116. static unsigned long cr3tab[] =    /* CRC polynomial 0xedb88320 */
  117. {
  118.   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
  119.   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
  120.   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
  121.   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
  122.   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
  123.   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
  124.   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
  125.   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
  126.   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
  127.   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
  128.   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
  129.   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
  130.   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
  131.   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
  132.   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
  133.   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
  134.   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
  135.   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
  136.   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
  137.   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  138.   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
  139.   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
  140.   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
  141.   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
  142.   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
  143.   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
  144.   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
  145.   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
  146.   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
  147.   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
  148.   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
  149.   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
  150.   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
  151.   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
  152.   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
  153.   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
  154.   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
  155.   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
  156.   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
  157.   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
  158.   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
  159.   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
  160.   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
  161. };
  162.  
  163. #define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))
  164.  
  165. static char *frametypes[] =
  166. {
  167.   "CARRIER_LOST",        /* -3 */
  168.   "TIMEOUT",            /* -2 */
  169.   "ERROR",            /* -1 */
  170. #define FTOFFSET 3
  171.   "ZRQINIT",
  172.   "ZRINIT",
  173.   "ZSINIT",
  174.   "ZACK",
  175.   "ZFILE",
  176.   "ZSKIP",
  177.   "ZNAK",
  178.   "ZABORT",
  179.   "ZFIN",
  180.   "ZRPOS",
  181.   "ZDATA",
  182.   "ZEOF",
  183.   "ZFERR",
  184.   "ZCRC",
  185.   "ZCHALLENGE",
  186.   "ZCOMPL",
  187.   "ZCAN",
  188.   "ZFREECNT",
  189.   "ZCOMMAND",
  190.   "ZSTDERR",
  191.   "xxxxx"
  192. #define FRTYPES 22        /* Total number of frame types in this array */
  193.             /*  not including psuedo negative entries */
  194. };
  195.  
  196. /**********************************************************
  197.  *      void zsbhdr(struct Vars *v, USHORT type)
  198.  *
  199.  * Send ZMODEM binary header hdr of type type
  200.  **********************************************************/
  201. void zsbhdr(struct Vars *v, USHORT type)
  202. {
  203.   UBYTE *hdr = v->Txhdr;
  204.   short n;
  205.   USHORT crc;
  206.   ULONG crc32;
  207.  
  208.   xsendline(v, ZPAD);
  209.   xsendline(v, ZDLE);
  210.  
  211.   if (v->Crc32t = v->Txfcs32)    /* zsbh32() */
  212.   {
  213.     xsendline(v, ZBIN32);
  214.     zsendline(v, (UBYTE) type);
  215.  
  216.     crc32 = 0xFFFFFFFFL;
  217.     crc32 = UPDC32(type, crc32);
  218.  
  219.     for (n = 4; --n >= 0; ++hdr)
  220.     {
  221.       crc32 = UPDC32((0377 & *hdr), crc32);
  222.       zsendline(v, *hdr);
  223.     }
  224.     crc32 = ~crc32;
  225.     for (n = 4; --n >= 0;)
  226.     {
  227.       zsendline(v, (int) crc32);
  228.       crc32 >>= 8;
  229.     }
  230.   }
  231.   else
  232.   {
  233.     xsendline(v, ZBIN);
  234.     zsendline(v, (UBYTE) type);
  235.  
  236.     crc = updcrc(type, 0);
  237.     for (n = 4; --n >= 0;)
  238.     {
  239.       zsendline(v, *hdr);
  240.       crc = updcrc(((USHORT) (*hdr++)), crc);
  241.     }
  242.  
  243.     crc = updcrc(((USHORT) 0), crc);
  244.     crc = updcrc(((USHORT) 0), crc);
  245.     zsendline(v, (UBYTE) (crc >> 8));
  246.     zsendline(v, (UBYTE) crc);
  247.   }
  248. }                /* End of void zsbhdr() */
  249.  
  250. /**********************************************************
  251.  *      void zshhdr(struct Vars *v, USHORT type)
  252.  *
  253.  * Send ZMODEM HEX header hdr of type type
  254.  **********************************************************/
  255. void zshhdr(struct Vars *v, USHORT type)
  256. {
  257.   UBYTE *hdr = v->Txhdr;
  258.   short n;
  259.   USHORT crc;
  260.  
  261.   sendline(v, ZPAD);
  262.   sendline(v, ZPAD);
  263.   sendline(v, ZDLE);
  264.   sendline(v, ZHEX);
  265.   zputhex(v, (UBYTE) type);
  266.   v->Crc32t = 0;
  267.  
  268.   crc = updcrc(type, 0);
  269.   for (n = 4; --n >= 0;)
  270.   {
  271.     zputhex(v, *hdr);
  272.     crc = updcrc(((USHORT) (*hdr++)), crc);
  273.   }
  274.  
  275.   crc = updcrc(((USHORT) 0), crc);
  276.   crc = updcrc(((USHORT) 0), crc);
  277.   zputhex(v, (UBYTE) (crc >> 8));
  278.   zputhex(v, (UBYTE) crc);
  279.  
  280.   /* Make it printable on remote machine */
  281.   sendline(v, '\r');
  282.   sendline(v, '\n');
  283.   /* Uncork the remote in case a fake XOFF has stopped data flow */
  284.   if (type != ZFIN)
  285.     sendline(v, XON);
  286. }                /* End of void zshhdr() */
  287.  
  288. /**********************************************************
  289.  *      void zsdata() and void zsda32()
  290.  *
  291.  * Send binary array buf of length length, with ending
  292.  * ZDLE sequence frameend
  293.  **********************************************************/
  294.  
  295. void zsdata(struct Vars *v, short length, USHORT frameend)
  296. {
  297.   UBYTE *buf;
  298.  
  299.   buf = v->Pktbuf;
  300.  
  301.   if (v->Crc32t)
  302.   {
  303.     short c;
  304.     ULONG crc;
  305.  
  306.     crc = 0xFFFFFFFFL;
  307.     for (; --length >= 0; ++buf)
  308.     {
  309.       c = *buf;
  310.       if (c & 0140)
  311.     xsendline(v, v->Lastzsent = c);
  312.       else
  313.     zsendline(v, c);
  314.       crc = UPDC32(c, crc);
  315.     }
  316.     xsendline(v, ZDLE);
  317.     xsendline(v, frameend);
  318.     crc = UPDC32(frameend, crc);
  319.  
  320.     crc = ~crc;
  321.     for (c = 4; --c >= 0;)
  322.     {
  323.       zsendline(v, (int) crc);
  324.       crc >>= 8;
  325.     }
  326.   }
  327.   else
  328.   {
  329.     register unsigned short crc;
  330.  
  331.     crc = 0;
  332.     for (; --length >= 0; ++buf)
  333.     {
  334.       zsendline(v, *buf);
  335.       crc = updcrc(*buf, crc);
  336.     }
  337.     xsendline(v, ZDLE);
  338.     xsendline(v, frameend);
  339.     crc = updcrc(frameend, crc);
  340.  
  341.     crc = updcrc(0, updcrc(0, crc));
  342.     zsendline(v, crc >> 8);
  343.     zsendline(v, crc);
  344.   }
  345.   if (frameend == ZCRCW)
  346.   {
  347.     xsendline(v, XON);
  348.   }
  349. }                /* End of void zsdata() */
  350.  
  351. /**********************************************************
  352.  *      short zrdata(struct Vars *v, UBYTE *buf, short length)
  353.  *
  354.  * Receive array buf of max length with ending ZDLE sequence
  355.  * and CRC-16.  Returns the ending character or error code.
  356.  **********************************************************/
  357. short zrdata(struct Vars *v, UBYTE * buf, short length)
  358. {
  359.   short c, d;
  360.   USHORT crc;
  361.  
  362.   if (v->Rxframeind == ZBIN32)
  363.     return zrdat32(v, buf, length);
  364.  
  365.   crc = v->Rxcount = 0;
  366.   for (;;)
  367.   {
  368.     if ((c = zdlread(v)) & ~0xFF)
  369.     {
  370.     crcfoo:
  371.       switch (c)
  372.       {
  373.       case GOTCRCE:
  374.       case GOTCRCG:
  375.       case GOTCRCQ:
  376.       case GOTCRCW:
  377.     crc = updcrc(((d = c) & 0xFF), crc);
  378.     if ((c = zdlread(v)) & ~0xFF)
  379.       goto crcfoo;
  380.     crc = updcrc(c, crc);
  381.     if ((c = zdlread(v)) & ~0xFF)
  382.       goto crcfoo;
  383.     crc = updcrc(c, crc);
  384.     if (crc & 0xFFFF)
  385.     {
  386.       strcpy(v->Msgbuf, GetLocaleString(MSG_BAD_DATA_CRC16_TXT));
  387.       return ERROR;
  388.     }
  389.     return d;
  390.       case GOTCAN:
  391.     strcpy(v->Msgbuf, GetLocaleString(MSG_SENDER_CANCELED_TXT));
  392.     return ZCAN;
  393.       case TIMEOUT:
  394.     strcpy(v->Msgbuf, GetLocaleString(MSG_DATA_PACKET_TIMEOUT_TXT));
  395.     return c;
  396.       case RCDO:
  397.     return c;
  398.       default:
  399.     strcpy(v->Msgbuf, GetLocaleString(MSG_UNRECOGNIZABLE_DATA_PACKET_TXT));
  400.     return c;
  401.       }
  402.     }
  403.     if (--length < 0)
  404.     {
  405.       strcpy(v->Msgbuf, GetLocaleString(MSG_DATA_PACKET_TOO_LONG_TXT));
  406.       return ERROR;
  407.     }
  408.     ++v->Rxcount;
  409.     *buf++ = c;
  410.     crc = updcrc(c, crc);
  411.     continue;
  412.   }
  413. }                /* End of short zrdata() */
  414.  
  415. /**********************************************************
  416.  *      short zrdat32(struct Vars *v, UBYTE *buf, short length)
  417.  *
  418.  * Receive array buf of max length with ending ZDLE sequence
  419.  * and CRC-32.  Returns the ending character or error code.
  420.  **********************************************************/
  421. short zrdat32(struct Vars *v, UBYTE * buf, short length)
  422. {
  423.   short c, d;
  424.   ULONG crc32;
  425.  
  426.   crc32 = 0xFFFFFFFFL;
  427.   v->Rxcount = 0;
  428.  
  429.   for (;;)
  430.   {
  431.     if ((c = zdlread(v)) & ~0xFF)
  432.     {
  433.     crcfoo:
  434.       switch (c)
  435.       {
  436.       case GOTCRCE:
  437.       case GOTCRCG:
  438.       case GOTCRCQ:
  439.       case GOTCRCW:
  440.     d = c;
  441.     c &= 0xFF;
  442.     crc32 = UPDC32(c, crc32);
  443.     if ((c = zdlread(v)) & ~0xFF)
  444.       goto crcfoo;
  445.     crc32 = UPDC32(c, crc32);
  446.     if ((c = zdlread(v)) & ~0xFF)
  447.       goto crcfoo;
  448.     crc32 = UPDC32(c, crc32);
  449.     if ((c = zdlread(v)) & ~0xFF)
  450.       goto crcfoo;
  451.     crc32 = UPDC32(c, crc32);
  452.     if ((c = zdlread(v)) & ~0xFF)
  453.       goto crcfoo;
  454.     crc32 = UPDC32(c, crc32);
  455.     if (crc32 != 0xDEBB20E3)
  456.     {
  457.       strcpy(v->Msgbuf, GetLocaleString(MSG_BAD_DATA_CRC32_TXT));
  458.       return ERROR;
  459.     }
  460.     return d;
  461.       case GOTCAN:
  462.     strcpy(v->Msgbuf, GetLocaleString(MSG_SENDER_CANCELED_TXT));
  463.     return ZCAN;
  464.       case TIMEOUT:
  465.     strcpy(v->Msgbuf, GetLocaleString(MSG_DATA_PACKET_TIMEOUT_TXT));
  466.     return c;
  467.       case RCDO:
  468.     return c;
  469.       default:
  470.     strcpy(v->Msgbuf, GetLocaleString(MSG_UNRECOGNIZABLE_DATA_PACKET_TXT));
  471.     return c;
  472.       }
  473.     }
  474.     if (--length < 0)
  475.     {
  476.       strcpy(v->Msgbuf, GetLocaleString(MSG_DATA_PACKET_TOO_LONG_TXT));
  477.       return ERROR;
  478.     }
  479.     ++v->Rxcount;
  480.     *buf++ = c;
  481.     crc32 = UPDC32(c, crc32);
  482.     continue;
  483.   }
  484. }                /* End of short zrdat32() */
  485.  
  486. /**********************************************************
  487.  *      short zgethdr(struct Vars *v)
  488.  *
  489.  * Read a ZMODEM header to hdr, either binary or hex.
  490.  *  On success return type of header.
  491.  *  Otherwise return negative on error.
  492.  **********************************************************/
  493. short zgethdr(struct Vars *v)
  494. {
  495.   short c, cancount;
  496.   long n;
  497.  
  498.   n = v->Baud;            /* Max characters before start of frame */
  499.   cancount = 5;
  500. again:
  501.   v->Rxframeind = v->Rxtype = 0;
  502.   switch (c = noxrd7(v))
  503.   {
  504.   case RCDO:
  505.   case TIMEOUT:
  506.     goto fifi;
  507.   case CAN:
  508.     if (--cancount <= 0)
  509.     {
  510.       c = ZCAN;
  511.       goto fifi;
  512.     }
  513.   case ZPAD:            /* This is what we want. */
  514.     break;
  515.   default:
  516.   agn2:
  517.     if (--n <= 0)
  518.     {
  519.       strcpy(v->Msgbuf, GetLocaleString(MSG_HEADER_SEARCH_GARBAGE_COUNT_EXCEEDED_TXT));
  520.       return ERROR;
  521.     }
  522.     if (c != CAN)
  523.       cancount = 5;
  524.     goto again;
  525.   }
  526.   cancount = 5;
  527. splat:
  528.   switch (c = noxrd7(v))
  529.   {
  530.   case ZPAD:
  531.     goto splat;
  532.   case RCDO:
  533.   case TIMEOUT:
  534.     goto fifi;
  535.   default:
  536.     goto agn2;
  537.   case ZDLE:            /* This is what we want. */
  538.     break;
  539.   }
  540.  
  541.   switch (c = noxrd7(v))
  542.   {
  543.   case RCDO:
  544.   case TIMEOUT:
  545.     goto fifi;
  546.   case ZBIN:
  547.     v->Rxframeind = ZBIN;
  548.     v->Crc32 = FALSE;
  549.     c = zrbhdr(v);
  550.     break;
  551.   case ZBIN32:
  552.     v->Crc32 = v->Rxframeind = ZBIN32;
  553.     c = zrbhdr32(v);
  554.     break;
  555.   case ZHEX:
  556.     v->Rxframeind = ZHEX;
  557.     v->Crc32 = FALSE;
  558.     c = zrhhdr(v);
  559.     break;
  560.   case CAN:
  561.     if (--cancount <= 0)
  562.     {
  563.       c = ZCAN;
  564.       goto fifi;
  565.     }
  566.     goto agn2;
  567.   default:
  568.     goto agn2;
  569.   }
  570.   v->Rxpos = rclhdr(v);
  571. fifi:
  572.   switch (c)
  573.   {
  574.   case GOTCAN:
  575.     c = ZCAN;
  576.   case ZNAK:
  577.   case ZCAN:
  578.   case ERROR:
  579.   case TIMEOUT:
  580.   case RCDO:
  581.     mysprintf(v->Msgbuf, "%s %s ", frametypes[c + FTOFFSET],
  582.           (c >= 0) ? GetLocaleString(MSG_HEADER_TXT) : GetLocaleString(MSG_ERROR_TXT));
  583.   }
  584.   return c;
  585. }                /* End of short zgethdr() */
  586.  
  587. /**********************************************************
  588.  *      short zrbhdr(struct Vars *v)
  589.  *
  590.  * Receive a binary style header (type and position)
  591.  **********************************************************/
  592. short zrbhdr(struct Vars *v)
  593. {
  594.   UBYTE *hdr = v->Rxhdr;
  595.   short c, n;
  596.   USHORT crc;
  597.  
  598.   if ((c = zdlread(v)) & ~0xFF)
  599.     return c;
  600.   v->Rxtype = c;
  601.   crc = updcrc(c, 0);
  602.  
  603.   for (n = 4; --n >= 0;)
  604.   {
  605.     if ((c = zdlread(v)) & ~0xFF)
  606.       return c;
  607.     crc = updcrc(c, crc);
  608.     *hdr++ = c;
  609.   }
  610.   if ((c = zdlread(v)) & ~0xFF)
  611.     return c;
  612.   crc = updcrc(c, crc);
  613.   if ((c = zdlread(v)) & ~0xFF)
  614.     return c;
  615.   crc = updcrc(c, crc);
  616.   if (crc & 0xFFFF)
  617.   {
  618.     strcpy(v->Msgbuf, GetLocaleString(MSG_BAD_HEADER_CRC16_TXT));
  619.     return ERROR;
  620.   }
  621.   return v->Rxtype;
  622. }                /* End of short zrbhdr() */
  623.  
  624. /**********************************************************
  625.  *      short zrbhdr32(struct Vars *v)
  626.  *
  627.  * Receive a binary style header (type and position) with
  628.  * 32 bit FCS
  629.  **********************************************************/
  630. short zrbhdr32(struct Vars *v)
  631. {
  632.   UBYTE *hdr = v->Rxhdr;
  633.   short c, n;
  634.   ULONG crc32;
  635.  
  636.   if ((c = zdlread(v)) & ~0xFF)
  637.     return c;
  638.   v->Rxtype = c;
  639.   crc32 = 0xFFFFFFFFL;
  640.   crc32 = UPDC32(c, crc32);
  641.  
  642.   for (n = 4; --n >= 0;)
  643.   {
  644.     if ((c = zdlread(v)) & ~0xFF)
  645.       return c;
  646.     crc32 = UPDC32(c, crc32);
  647.     *hdr++ = c;
  648.   }
  649.   for (n = 4; --n >= 0;)
  650.   {
  651.     if ((c = zdlread(v)) & ~0xFF)
  652.       return c;
  653.     crc32 = UPDC32(c, crc32);
  654.   }
  655.   if (crc32 != 0xDEBB20E3)
  656.   {
  657.     strcpy(v->Msgbuf, GetLocaleString(MSG_BAD_HEADER_CRC32_TXT));
  658.     return ERROR;
  659.   }
  660.   return v->Rxtype;
  661. }                /* End of short zrbhdr32() */
  662.  
  663. /**********************************************************
  664.  *      short zrhhdr(struct Vars *v)
  665.  *
  666.  * Receive a hex style header (type and position)
  667.  **********************************************************/
  668. short zrhhdr(struct Vars *v)
  669. {
  670.   UBYTE *hdr = v->Rxhdr;
  671.   short c, n;
  672.   USHORT crc;
  673.  
  674.   if ((c = zgethex(v)) < 0)
  675.     return c;
  676.   v->Rxtype = c;
  677.   crc = updcrc(c, 0);
  678.  
  679.   for (n = 4; --n >= 0;)
  680.   {
  681.     if ((c = zgethex(v)) < 0)
  682.       return c;
  683.     crc = updcrc(c, crc);
  684.     *hdr++ = c;
  685.   }
  686.   if ((c = zgethex(v)) < 0)
  687.     return c;
  688.   crc = updcrc(c, crc);
  689.   if ((c = zgethex(v)) < 0)
  690.     return c;
  691.   crc = updcrc(c, crc);
  692.   if (crc & 0xFFFF)
  693.   {
  694.     strcpy(v->Msgbuf, GetLocaleString(MSG_BAD_HEADER_CRC_TXT));
  695.     return ERROR;
  696.   }
  697.   if (readock(v, 1) == '\r')
  698.     readock(v, 1);        /* Throw away possible cr/lf */
  699.   return v->Rxtype;
  700. }                /* End of short zrhhdr() */
  701.  
  702. /**********************************************************
  703.  *      void zputhex(struct Vars *v, UBYTE c)
  704.  *
  705.  * Send a byte as two hex digits
  706.  **********************************************************/
  707. void zputhex(struct Vars *v, UBYTE c)
  708. {
  709.   static char digits[] = "0123456789abcdef";
  710.  
  711.   sendline(v, digits[(c >> 4) & 0x0F]);
  712.   sendline(v, digits[c & 0x0F]);
  713. }                /* End of void zputhex() */
  714.  
  715. /**********************************************************
  716.  *      void zsendline(struct Vars *v, UBYTE c)
  717.  *
  718.  * Send character c with ZMODEM escape sequence encoding.
  719.  * Escape ZDLE, real DLE, XON, XOFF, and CR following @ (Telenet net escape)
  720.  **********************************************************/
  721. void zsendline(struct Vars *v, UBYTE c)
  722. {
  723.   static char actions[256] =
  724.   {
  725.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3,
  726.     2, 2, 3, 2, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
  727.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  728.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  729.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  730.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  731.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  732.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  733.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3,
  734.     2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  735.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  736.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  737.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  738.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  739.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  740.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  741.   };
  742.  
  743.   switch (actions[c])
  744.   {
  745.   case 0:
  746.     xsendline(v, ZDLE);
  747.     xsendline(v, v->Lastzsent = (c ^ 0100));
  748.     break;
  749.  
  750.   case 1:
  751.     if (!v->Zctlesc && (v->Lastzsent & 0177) != '@')
  752.       goto sendit;
  753.  
  754.     /* **** FALL THRU TO **** */
  755.  
  756.   case 2:
  757.     xsendline(v, ZDLE);
  758.     c ^= 0100;
  759.  
  760.   sendit:xsendline(v, v->Lastzsent = c);
  761.     break;
  762.  
  763.   case 3:
  764.     if (v->Zctlesc && !(c & 0140))
  765.     {
  766.       xsendline(v, ZDLE);
  767.       c ^= 0100;
  768.     }
  769.  
  770.     xsendline(v, v->Lastzsent = c);
  771.     break;
  772.   }
  773. }                /* End of void zsendline() */
  774.  
  775.  
  776. /**********************************************************
  777.  *      short zgethex(struct Vars *v)
  778.  *
  779.  * Decode two lower case hex digits into an 8 bit byte value
  780.  **********************************************************/
  781. short zgethex(struct Vars *v)
  782. {
  783.   short c, n;
  784.  
  785.   if ((n = noxrd7(v)) < 0)
  786.     return n;
  787.   n -= '0';
  788.   if (n > 9)
  789.     n -= ('a' - ':');
  790.   if (n & ~0xF)
  791.     return ERROR;
  792.  
  793.   if ((c = noxrd7(v)) < 0)
  794.     return c;
  795.   c -= '0';
  796.   if (c > 9)
  797.     c -= ('a' - ':');
  798.   if (c & ~0xF)
  799.     return ERROR;
  800.  
  801.   return (short) (n << 4 | c);
  802. }                /* End of short zgethex() */
  803.  
  804. /**********************************************************
  805.  *      short zdlread(struct Vars *v)
  806.  *
  807.  * Read a byte, checking for ZMODEM escape encoding
  808.  * including CAN*5 which represents a quick abort.
  809.  **********************************************************/
  810. short zdlread(struct Vars *v)
  811. {
  812.   register short c;
  813.  
  814. again:
  815.   /* Quick check for non control characters */
  816.   if ((c = readock(v, v->Rxtimeout)) & 0140)
  817.     return c;
  818.   switch (c)
  819.   {
  820.   case ZDLE:
  821.     break;
  822.   case 023:
  823.   case 0223:
  824.   case 021:
  825.   case 0221:
  826.     goto again;
  827.   default:
  828.     if (v->Zctlesc && !(c & 0140))
  829.     {
  830.       goto again;
  831.     }
  832.     return c;
  833.   }
  834. again2:
  835.   if ((c = readock(v, v->Rxtimeout)) < 0)
  836.     return c;
  837.   if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  838.     return c;
  839.   if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  840.     return c;
  841.   if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  842.     return c;
  843.   switch (c)
  844.   {
  845.   case CAN:
  846.     return GOTCAN;
  847.   case ZCRCE:
  848.   case ZCRCG:
  849.   case ZCRCQ:
  850.   case ZCRCW:
  851.     return ((short) (c | GOTOR));
  852.   case ZRUB0:
  853.     return 0177;
  854.   case ZRUB1:
  855.     return 0377;
  856.   case 023:
  857.   case 0223:
  858.   case 021:
  859.   case 0221:
  860.     goto again2;
  861.   default:
  862.     if (v->Zctlesc && !(c & 0140))
  863.     {
  864.       goto again2;
  865.     }
  866.     if ((c & 0140) == 0100)
  867.       return ((short) (c ^ 0100));
  868.     break;
  869.   }
  870.   strcpy(v->Msgbuf, GetLocaleString(MSG_BAD_ZMODEM_ESC_TXT));
  871.   return ERROR;
  872. }                /* End of short zdlread() */
  873.  
  874. /**********************************************************
  875.  *      short noxrd7(struct Vars *v)
  876.  *
  877.  * Read a character from the modem line with timeout.
  878.  * Eat parity, XON and XOFF characters.
  879.  **********************************************************/
  880. short noxrd7(struct Vars *v)
  881. {
  882.   short c;
  883.  
  884.   for (;;)
  885.   {
  886.     if ((c = readock(v, v->Rxtimeout)) < 0)
  887.       return c;
  888.     switch (c &= 0x7F)
  889.     {
  890.     case XON:
  891.     case XOFF:
  892.       continue;
  893.     default:
  894.       if (v->Zctlesc && !(c & 0140))
  895.     continue;
  896.     case '\r':
  897.     case '\n':
  898.     case ZDLE:
  899.       return c;
  900.     }
  901.   }
  902. }                /* short noxrd7() */
  903.  
  904. /**********************************************************
  905.  *      void stohdr(struct Vars *v, long pos)
  906.  *
  907.  * Store long integer pos in Txhdr
  908.  **********************************************************/
  909. void stohdr(struct Vars *v, long pos)
  910. {
  911.   v->Txhdr[ZP0] = pos;
  912.   pos >>= 8;
  913.   v->Txhdr[ZP1] = pos;
  914.   pos >>= 8;
  915.   v->Txhdr[ZP2] = pos;
  916.   pos >>= 8;
  917.   v->Txhdr[ZP3] = pos;
  918. }                /* End of void stohdr() */
  919.  
  920. /**********************************************************
  921.  *      long rclhdr(struct Vars *v)
  922.  *
  923.  * Recover a long integer from a header
  924.  **********************************************************/
  925. long rclhdr(struct Vars *v)
  926. {
  927.   long l;
  928.  
  929.   l = v->Rxhdr[ZP3];
  930.   l = (l << 8) | v->Rxhdr[ZP2];
  931.   l = (l << 8) | v->Rxhdr[ZP1];
  932.   l = (l << 8) | v->Rxhdr[ZP0];
  933.   return l;
  934. }                /* End of long rclhdr() */
  935. /* End of Zm.c source */
  936.