home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff236.lzh / XprZmodem / zm.c < prev    next >
C/C++ Source or Header  |  1989-08-09  |  11KB  |  493 lines

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