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