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