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 / ENTERPRS / CPM / TERMS / ZMODEM.ZIP / ZM.C < prev    next >
Text File  |  1987-09-28  |  10KB  |  486 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    6-09-86  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. #ifndef CANFDX
  17. #include "zmodem.h"
  18. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  19. #endif
  20.  
  21. static char *frametypes[] = {
  22.     "TIMEOUT",
  23.     "ERROR",
  24.     "ZRQINIT",
  25.     "ZRINIT",
  26.     "ZSINIT",
  27.     "ZACK",
  28.     "ZFILE",
  29.     "ZSKIP",
  30.     "ZNAK",
  31.     "ZABORT",
  32.     "ZFIN",
  33.     "ZRPOS",
  34.     "ZDATA",
  35.     "ZEOF",
  36.     "ZFERR",
  37.     "ZCRC",
  38.     "ZCHALLENGE",
  39.     "ZCOMPL",
  40.     "ZCAN",
  41.     "ZFREECNT",
  42.     "ZCOMMAND",
  43.     "ZSTDERR",
  44.     "xxxxx"
  45. #define FRTYPES 22    /* Total number of frame types in this array */
  46. };
  47.  
  48. /* Send ZMODEM binary header hdr of type type */
  49. zsbhdr(type, hdr)
  50. register char *hdr;
  51. {
  52.     register n;
  53.     register unsigned short oldcrc;
  54.  
  55.     vfile("zsbhdr: %s %lx", frametypes[type+2], rclhdr(hdr));
  56.     xsendline(ZPAD); xsendline(ZDLE); xsendline(ZBIN);
  57.  
  58.     zsendline(type); oldcrc = updcrc(type, 0);
  59.  
  60.     for (n=4; --n >= 0;) {
  61.         zsendline(*hdr);
  62.         oldcrc = updcrc(*hdr++, oldcrc);
  63.     }
  64.     oldcrc = updcrc(0,updcrc(0,oldcrc));
  65.     zsendline(oldcrc>>8);
  66.     zsendline(oldcrc);
  67.     if (type != ZDATA)
  68.         flushmo();
  69. }
  70.  
  71. /* Send ZMODEM HEX header hdr of type type */
  72. zshhdr(type, hdr)
  73. register char *hdr;
  74. {
  75.     register n;
  76.     register unsigned short oldcrc;
  77.  
  78.     vfile("zshhdr: %s %lx", frametypes[type+2], rclhdr(hdr));
  79.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  80.     zputhex(type);
  81.  
  82.     oldcrc = updcrc(type, 0);
  83.     for (n=4; --n >= 0;) {
  84.         zputhex(*hdr); oldcrc = updcrc(*hdr++, oldcrc);
  85.     }
  86.     oldcrc = updcrc(0,updcrc(0,oldcrc));
  87.     zputhex(oldcrc>>8); zputhex(oldcrc);
  88.  
  89.     /* Make it printable on remote machine */
  90.     sendline(015); sendline(012);
  91.     /*
  92.      * Uncork the remote in case a fake XOFF has stopped data flow
  93.      */
  94.     if (type != ZFIN)
  95.         sendline(021);
  96.     flushmo();
  97. }
  98.  
  99. /*
  100.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  101.  */
  102. zsdata(buf, length, frameend)
  103. register char *buf;
  104. {
  105.     register unsigned short oldcrc;
  106.  
  107.     vfile("zsdata: length=%d end=%x", length, frameend);
  108.     oldcrc = 0;
  109.     for (;--length >= 0;) {
  110.         zsendline(*buf);
  111.         oldcrc = updcrc(*buf++, oldcrc);
  112.     }
  113.     xsendline(ZDLE); xsendline(frameend);
  114.     oldcrc = updcrc(frameend, oldcrc);
  115.  
  116.     oldcrc = updcrc(0,updcrc(0,oldcrc));
  117.     zsendline(oldcrc>>8);
  118.     zsendline(oldcrc);
  119.     if (frameend == ZCRCW)
  120.         flushmo();
  121. }
  122.  
  123. /*
  124.  * Receive array buf of max length with ending ZDLE sequence
  125.  *  and CRC.  Returns the ending character or error code.
  126.  */
  127. zrdata(buf, length)
  128. register char *buf;
  129. {
  130.     register c;
  131.     register unsigned short oldcrc;
  132.     register d;
  133.  
  134.     oldcrc = Rxcount = 0;
  135.     for (;;) {
  136.         if ((c = zdlread()) & ~0377) {
  137.             switch (c) {
  138.             case GOTCRCE:
  139.             case GOTCRCG:
  140.             case GOTCRCQ:
  141.             case GOTCRCW:
  142.                 oldcrc = updcrc((d=c)&0377, oldcrc);
  143.                 if ((c = zdlread()) & ~0377)
  144.                     goto badcrc;
  145.                 oldcrc = updcrc(c, oldcrc);
  146.                 if ((c = zdlread()) & ~0377)
  147.                     goto badcrc;
  148.                 oldcrc = updcrc(c, oldcrc);
  149.                 if (oldcrc & 0xFFFF) {
  150. badcrc:
  151.                     zperr("Bad data packet CRC");
  152.                     return ERROR;
  153.                 }
  154.                 vfile("zrdata: Rxcount = %d ret = %x",
  155.                   Rxcount, d);
  156.                 return d;
  157.             case GOTCAN:
  158.                 zperr("ZMODEM: Sender Canceled");
  159.                 return ZCAN;
  160.             case TIMEOUT:
  161.                 zperr("ZMODEM data packet TIMEOUT");
  162.                 return c;
  163.             default:
  164.                 zperr("ZMODEM bad data packet ret=%x", c);
  165.                 return c;
  166.             }
  167.         }
  168.         if (--length < 0) {
  169.             zperr("ZMODEM data packet too long");
  170.             return ERROR;
  171.         }
  172.         ++Rxcount;
  173.         *buf++ = c;
  174.         oldcrc = updcrc(c, oldcrc);
  175.         continue;
  176.     }
  177. }
  178.  
  179. /*
  180.  * Read a ZMODEM header to hdr, either binary or hex.
  181.  *  eflag controls local display of non zmodem characters:
  182.  *    0:  no display
  183.  *    1:  display printing characters only
  184.  *    2:  display all non ZMODEM characters
  185.  *  On success, set Zmodem to 1 and return type of header.
  186.  *   Otherwise return negative on error
  187.  */
  188. zgethdr(hdr, eflag)
  189. char *hdr;
  190. {
  191.     register c, n, cancount;
  192.  
  193.     n = Baudrate;    /* Max characters before start of frame */
  194.     cancount = 5;
  195. again:
  196.     Rxframeind = Rxtype = 0;
  197.     switch (c = noxread7()) {
  198.     case TIMEOUT:
  199.         goto fifi;
  200.     case CAN:
  201.         if (--cancount <= 0) {
  202.             c = ZCAN; goto fifi;
  203.         }
  204.     /* **** FALL THRU TO **** */
  205.     default:
  206. agn2:
  207.         if ( --n == 0) {
  208.             zperr("ZMODEM Garbage count exceeded");
  209.             return(ERROR);
  210.         }
  211.         if (eflag && ((c &= 0177) & 0140))
  212.             bttyout(c);
  213.         else if (eflag > 1)
  214.             bttyout(c);
  215.         if (c != CAN)
  216.             cancount = 5;
  217.         goto again;
  218.     case ZPAD:        /* This is what we want. */
  219.         break;
  220.     }
  221.     cancount = 5;
  222. splat:
  223.     switch (c = noxread7()) {
  224.     case ZPAD:
  225.         goto splat;
  226.     case TIMEOUT:
  227.         goto fifi;
  228.     default:
  229.         goto agn2;
  230.     case ZDLE:        /* This is what we want. */
  231.         break;
  232.     }
  233.  
  234.     switch (c = noxread7()) {
  235.     case TIMEOUT:
  236.         goto fifi;
  237.     case ZBIN:
  238.         Rxframeind = ZBIN;
  239.         c =  zrbhdr(hdr);
  240.         break;
  241.     case ZHEX:
  242.         Rxframeind = ZHEX;
  243.         c =  zrhhdr(hdr);
  244.         break;
  245.     case CAN:
  246.         if (--cancount <= 0) {
  247.             c = ZCAN; goto fifi;
  248.         }
  249.         goto agn2;
  250.     default:
  251.         goto agn2;
  252.     }
  253.     Rxpos = hdr[ZP3] & 0377;
  254.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  255.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  256.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  257. fifi:
  258.     switch (c) {
  259.     case GOTCAN:
  260.         c = ZCAN;
  261.     /* **** FALL THRU TO **** */
  262.     case ZNAK:
  263.     case ZCAN:
  264.     case ERROR:
  265.     case TIMEOUT:
  266.         zperr("ZMODEM: Got %s header", frametypes[c+2]);
  267.     default:
  268.         if (c >= -2 && c <= FRTYPES)
  269.             vfile("zgethdr: %s %lx", frametypes[c+2], Rxpos);
  270.         else
  271.             vfile("zgethdr: %d %lx", c, Rxpos);
  272.     }
  273.     return c;
  274. }
  275.  
  276. /* Receive a binary style header (type and position) */
  277. zrbhdr(hdr)
  278. register char *hdr;
  279. {
  280.     register c, n;
  281.     register unsigned short oldcrc;
  282.  
  283.     if ((c = zdlread()) & ~0377)
  284.         return c;
  285.     Rxtype = c;
  286.     oldcrc = updcrc(c, 0);
  287.  
  288.     for (n=4; --n >= 0;) {
  289.         if ((c = zdlread()) & ~0377)
  290.             return c;
  291.         oldcrc = updcrc(c, oldcrc);
  292.         *hdr++ = c;
  293.     }
  294.     if ((c = zdlread()) & ~0377)
  295.         return c;
  296.     oldcrc = updcrc(c, oldcrc);
  297.     if ((c = zdlread()) & ~0377)
  298.         return c;
  299.     oldcrc = updcrc(c, oldcrc);
  300.     if (oldcrc & 0xFFFF) {
  301.         zperr("Bad Header CRC"); return ERROR;
  302.     }
  303.     Zmodem = 1;
  304.     return Rxtype;
  305. }
  306.  
  307. /* Receive a hex style header (type and position) */
  308. zrhhdr(hdr)
  309. char *hdr;
  310. {
  311.     register c;
  312.     register unsigned short oldcrc;
  313.     register n;
  314.  
  315.     if ((c = zgethex()) < 0)
  316.         return c;
  317.     Rxtype = c;
  318.     oldcrc = updcrc(c, 0);
  319.  
  320.     for (n=4; --n >= 0;) {
  321.         if ((c = zgethex()) < 0)
  322.             return c;
  323.         oldcrc = updcrc(c, oldcrc);
  324.         *hdr++ = c;
  325.     }
  326.     if ((c = zgethex()) < 0)
  327.         return c;
  328.     oldcrc = updcrc(c, oldcrc);
  329.     if ((c = zgethex()) < 0)
  330.         return c;
  331.     oldcrc = updcrc(c, oldcrc);
  332.     if (oldcrc & 0xFFFF) {
  333.         zperr("Bad Header CRC"); return ERROR;
  334.     }
  335.     if (readline(1) == '\r')    /* Throw away possible cr/lf */
  336.         readline(1);
  337.     Zmodem = 1; return Rxtype;
  338. }
  339.  
  340. /* Send a byte as two hex digits */
  341. zputhex(c)
  342. register c;
  343. {
  344.     static char    digits[]    = "0123456789abcdef";
  345.  
  346.     if (Verbose>4)
  347.         vfile("zputhex: %x", c);
  348.     sendline(digits[(c&0xF0)>>4]);
  349.     sendline(digits[(c)&0xF]);
  350. }
  351.  
  352. /* Send character c with ZMODEM escape sequence encoding */
  353. zsendline(c)
  354. register c;
  355. {
  356.     switch (c & 0377) {
  357.     case ZDLE:
  358.     case 021:
  359.     case 023:
  360.     case 0221:
  361.     case 0223:
  362.         xsendline(ZDLE);
  363.         c ^= 0100;
  364.     /* **** FALL THRU TO **** */
  365.     default:
  366.         xsendline(c);
  367.     }
  368. }
  369.  
  370. /* Decode two lower case hex digits into an 8 bit byte value */
  371. zgethex()
  372. {
  373.     register c;
  374.  
  375.     c = zgeth1();
  376.     if (Verbose>4)
  377.         vfile("zgethex: %x", c);
  378.     return c;
  379. }
  380. zgeth1()
  381. {
  382.     register c, n;
  383.  
  384.     if ((c = noxread7()) < 0)
  385.         return c;
  386.     n = c - '0';
  387.     if (n > 9)
  388.         n -= ('a' - ':');
  389.     if (n & ~0xF)
  390.         return ERROR;
  391.     if ((c = noxread7()) < 0)
  392.         return c;
  393.     c -= '0';
  394.     if (c > 9)
  395.         c -= ('a' - ':');
  396.     if (c & ~0xF)
  397.         return ERROR;
  398.     c += (n<<4);
  399.     return c;
  400. }
  401.  
  402. /*
  403.  * Read a byte, checking for ZMODEM escape encoding
  404.  *  including CAN*5 which represents a quick abort
  405.  */
  406. zdlread()
  407. {
  408.     register c;
  409.  
  410.     if ((c = readline(Rxtimeout)) != ZDLE)
  411.         return c;
  412.     if ((c = readline(Rxtimeout)) < 0)
  413.         return c;
  414.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  415.         return c;
  416.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  417.         return c;
  418.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  419.         return c;
  420.     switch (c) {
  421.     case CAN:
  422.         return GOTCAN;
  423.     case ZCRCE:
  424.     case ZCRCG:
  425.     case ZCRCQ:
  426.     case ZCRCW:
  427.         return (c | GOTOR);
  428.     case ZRUB0:
  429.         return 0177;
  430.     case ZRUB1:
  431.         return 0377;
  432.     default:
  433.         if ((c & 0140) ==  0100)
  434.             return (c ^ 0100);
  435.         break;
  436.     }
  437.     zperr("Got bad ZMODEM escape sequence %x", c);
  438.     return ERROR;
  439. }
  440.  
  441. /*
  442.  * Read a character from the modem line with timeout.
  443.  *  Eat parity, XON and XOFF characters.
  444.  */
  445. noxread7()
  446. {
  447.     register c;
  448.  
  449.     for (;;) {
  450.         if ((c = readline(Rxtimeout)) < 0)
  451.             return c;
  452.         switch (c &= 0177) {
  453.         case XON:
  454.         case XOFF:
  455.             continue;
  456.         default:
  457.             return c;
  458.         }
  459.     }
  460. }
  461.  
  462. /* Store long integer pos in Txhdr */
  463. stohdr(pos)
  464. long pos;
  465. {
  466.     Txhdr[ZP0] = pos;
  467.     Txhdr[ZP1] = pos>>8;
  468.     Txhdr[ZP2] = pos>>16;
  469.     Txhdr[ZP3] = pos>>24;
  470. }
  471.  
  472. /* Recover a long integer from a header */
  473. long
  474. rclhdr(hdr)
  475. register char *hdr;
  476. {
  477.     register long l;
  478.  
  479.     l = (hdr[ZP3] & 0377);
  480.     l = (l << 8) | (hdr[ZP2] & 0377);
  481.     l = (l << 8) | (hdr[ZP1] & 0377);
  482.     l = (l << 8) | (hdr[ZP0] & 0377);
  483.     return l;
  484. }
  485.  
  486.