home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / ftp.vapor.com / microdot-1 / md1_src_02.lzx / zm.c < prev    next >
C/C++ Source or Header  |  2014-05-19  |  19KB  |  798 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.  
  16. /*#include <proto/all.h>
  17. #include <exec/types.h>
  18. #include <ctype.h>
  19. #include <stdio.h>*/
  20.  
  21. #include <string.h>
  22.  
  23. #include "xproto.h"
  24. #include "zmodem.h"
  25. #include "xprzmodem.h"
  26. #include "zcrc.h"
  27.  
  28. static char *frametypes[] =
  29. {
  30.    "Carrier Lost",         /* -3 */
  31.    "TIMEOUT",              /* -2 */
  32.    "ERROR",                /* -1 */
  33. #define FTOFFSET 3
  34.    "ZRQINIT",
  35.    "ZRINIT",
  36.    "ZSINIT",
  37.    "ZACK",
  38.    "ZFILE",
  39.    "ZSKIP",
  40.    "ZNAK",
  41.    "ZABORT",
  42.    "ZFIN",
  43.    "ZRPOS",
  44.    "ZDATA",
  45.    "ZEOF",
  46.    "ZFERR",
  47.    "ZCRC",
  48.    "ZCHALLENGE",
  49.    "ZCOMPL",
  50.    "ZCAN",
  51.    "ZFREECNT",
  52.    "ZCOMMAND",
  53.    "ZSTDERR",
  54.    "xxxxx"
  55. #define FRTYPES 22      /* Total number of frame types in this array */
  56.                         /*  not including psuedo negative entries */
  57.    };
  58.  
  59. static UBYTE DLE_actions[] =
  60. {
  61.    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,
  62.    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,
  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.  
  66.    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,
  67.    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,
  68.    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,
  69.    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
  70.    };
  71.  
  72. /**********************************************************
  73.  *    void zsbhdr(struct Vars *v, USHORT type)
  74.  *
  75.  * Send ZMODEM binary header hdr of type type
  76.  **********************************************************/
  77. void zsbhdr(struct Vars *v, USHORT type)
  78. {
  79.    UBYTE  *hdr = v->Txhdr;
  80.    int  n;
  81.    ULONG  crc32;
  82.    USHORT crc;
  83.  
  84.    xsendline(v, ZPAD);
  85.    xsendline(v, ZDLE);
  86.  
  87.    if (v->Crc32t = v->Txfcs32)    /* zsbh32() */
  88.    {
  89.       xsendline(v, ZBIN32);
  90.       zsendline(v, (UBYTE) type);
  91.  
  92. #ifdef DEBUGLOG
  93.       mysprintf(v->Msgbuf, "zsbh32: %s %lx\n", frametypes[type + FTOFFSET],
  94.          v->Txpos);
  95.       dlog(v, v->Msgbuf);
  96. #endif
  97.       crc32 = 0xFFFFFFFFL;
  98.       crc32 = UPDC32(type, crc32);
  99.  
  100.       for (n = 4; --n >= 0; ++hdr)
  101.       {
  102.      crc32 = UPDC32((0377 & *hdr), crc32);
  103.      zsendline(v, *hdr);
  104.      }
  105.       crc32 = ~crc32;
  106.       for (n = 4; --n >= 0;)
  107.       {
  108.      zsendline(v, (int) crc32);
  109.      crc32 >>= 8;
  110.      }
  111.       }
  112.    else
  113.    {
  114.       xsendline(v, ZBIN);
  115.       zsendline(v, (UBYTE) type);
  116.  
  117. #ifdef DEBUGLOG
  118.       mysprintf(v->Msgbuf, "zsbhdr: %s %lx\n", frametypes[type + FTOFFSET],
  119.          v->Txpos);
  120.       dlog(v, v->Msgbuf);
  121. #endif
  122.       crc = updcrc(type, 0);
  123.       for (n = 4; --n >= 0; )
  124.       {
  125.      zsendline(v, *hdr);
  126.      crc = updcrc(((USHORT) (*hdr++)), crc);
  127.      }
  128.  
  129.       crc = updcrc(((USHORT) 0), crc);
  130.       crc = updcrc(((USHORT) 0), crc);
  131.       zsendline(v, (UBYTE) (crc >> 8));
  132.       zsendline(v, (UBYTE) crc);
  133.       }
  134.    }    /* End of void zsbhdr() */
  135.  
  136. /**********************************************************
  137.  *    void zshhdr(struct Vars *v, USHORT type)
  138.  *
  139.  * Send ZMODEM HEX header hdr of type type
  140.  **********************************************************/
  141. void zshhdr(struct Vars *v, USHORT type)
  142. {
  143.    UBYTE *hdr = v->Txhdr;
  144.    int n;
  145.    USHORT crc;
  146.  
  147. #ifdef DEBUGLOG
  148.    mysprintf(v->Msgbuf, "zshhdr: %s %lx\n", frametypes[type + FTOFFSET],
  149.       v->Rxbytes);
  150.    dlog(v, v->Msgbuf);
  151. #endif
  152.    sendline(v, ZPAD);
  153.    sendline(v, ZPAD);
  154.    sendline(v, ZDLE);
  155.    sendline(v, ZHEX);
  156.    zputhex(v, (UBYTE) type);
  157.    v->Crc32t = 0;
  158.  
  159.    crc = updcrc(type, 0);
  160.    for (n = 4; --n >= 0; )
  161.    {
  162.       zputhex(v, *hdr);
  163.       crc = updcrc(((USHORT) (*hdr++)), crc);
  164.       }
  165.  
  166.    crc = updcrc(((USHORT) 0), crc);
  167.    crc = updcrc(((USHORT) 0), crc);
  168.    zputhex(v, (UBYTE) (crc >> 8));
  169.    zputhex(v, (UBYTE) crc);
  170.  
  171.    /* Make it printable on remote machine */
  172.    sendline(v, '\r');
  173.    sendline(v, '\n');
  174.    /* Uncork the remote in case a fake XOFF has stopped data flow */
  175.    if (type != ZFIN)
  176.       sendline(v, XON);
  177.    }    /* End of void zshhdr() */
  178.  
  179. /**********************************************************
  180.  *    void zsdata() and void zsda32()
  181.  *
  182.  * Send binary array buf of length length, with ending
  183.  * ZDLE sequence frameend
  184.  **********************************************************/
  185. void zsdata(struct Vars *v, short length, USHORT frameend)
  186. {
  187.    UBYTE  *buf, *outptr, c;
  188.    USHORT crc;
  189.    ULONG  crc32;
  190.  
  191. #ifdef DEBUGLOG
  192.    mysprintf(v->Msgbuf, v->Crc32t ? "zsda32: length=%ld end=%lx\n" 
  193.       : "zsdata: length=%ld end=%lx\n", (long) length, (long) frameend);
  194.    dlog(v, v->Msgbuf);
  195. #endif
  196.  
  197.    buf = v->Pktbuf;
  198.    outptr = v->Outbuf + v->Outbuflen;
  199.    crc32 = 0xFFFFFFFFL;            /* zsda32() */
  200.    crc = 0;
  201.  
  202.    while (--length >= 0)
  203.    {
  204.       switch (DLE_actions[c = *buf])
  205.       {
  206.       case 2:
  207.          if (v->Lastzsent != '@')
  208.             goto sendit;
  209.          /* Fallthrough */
  210.       case 1:
  211.          *outptr++ = ZDLE;
  212.          c ^= 0x40;
  213. sendit:
  214.       case 0:
  215.          *outptr++ = v->Lastzsent = c;
  216.          }
  217.       if (v->Crc32t)            /* zsda32() */
  218.      crc32 = UPDC32((0xFF & *buf++), crc32);
  219.       else
  220.      crc = updcrc(((USHORT) (*buf++)), crc);
  221.       }
  222.    *outptr++ = ZDLE;
  223.    *outptr++ = frameend;
  224.    v->Outbuflen = outptr - v->Outbuf;
  225.  
  226.    if (v->Crc32t)                /* zsda32() */
  227.    {
  228.       crc32 = UPDC32(frameend, crc32);
  229.       crc32 = ~crc32;
  230.       for (length = 4; --length >= 0; )
  231.       {
  232.      zsendline(v, (int) crc32);
  233.      crc32 >>= 8;
  234.      }
  235.       }
  236.    else
  237.    {
  238.       crc = updcrc(frameend, crc);
  239.       crc = updcrc(((USHORT) 0), crc);
  240.       crc = updcrc(((USHORT) 0), crc);
  241.       zsendline(v, (UBYTE) (crc >> 8));
  242.       zsendline(v, (UBYTE) crc);
  243.       }
  244.  
  245.    if (frameend == ZCRCW)
  246.       xsendline(v, XON);
  247.    }    /* End of void zsdata() */
  248.  
  249. /**********************************************************
  250.  *    short zrdata(struct Vars *v, UBYTE *buf, short length)
  251.  *
  252.  * Receive array buf of max length with ending ZDLE sequence
  253.  * and CRC-16.  Returns the ending character or error code.
  254.  **********************************************************/
  255. int zrdata(struct Vars *v, UBYTE *buf, short length)
  256. {
  257.    int c, d;
  258.    USHORT crc;
  259.  
  260.    if (v->Rxframeind == ZBIN32)
  261.       return zrdat32(v, buf, length);
  262.  
  263.    crc = v->Rxcount = 0;
  264.    for (;;)
  265.    {
  266.       if ((c = zdlread(v)) & ~0xFF)
  267.       {
  268. crcfoo:
  269.          switch (c)
  270.      {
  271.          case GOTCRCE:
  272.          case GOTCRCG:
  273.          case GOTCRCQ:
  274.          case GOTCRCW:
  275.             crc = updcrc(((d = c) & 0xFF), crc);
  276.             if ((c = zdlread(v)) & ~0xFF)
  277.            goto crcfoo;
  278.             crc = updcrc(c, crc);
  279.             if ((c = zdlread(v)) & ~0xFF)
  280.            goto crcfoo;
  281.             crc = updcrc(c, crc);
  282.             if (crc & 0xFFFF)
  283.         {
  284.                strcpy(v->Msgbuf, "CRC-Fehler in Datenpaket ");
  285.                return ERROR;
  286.                }
  287. #ifdef DEBUGLOG
  288.             mysprintf(v->Msgbuf, "zrdata: cnt = %ld ret = %lx\n",
  289.            (long) v->Rxcount, (long) d);
  290.             dlog(v, v->Msgbuf);
  291. #endif
  292.             return d;
  293.          case GOTCAN:
  294.             strcpy(v->Msgbuf, "Sender hat abgebrochen ");
  295.             return ZCAN;
  296.          case TIMEOUT:
  297.             strcpy(v->Msgbuf, "Paket-Timeout ");
  298.             return c;
  299.          case RCDO:
  300.             return c;
  301.          default:
  302.             strcpy(v->Msgbuf, "Unbekanntes Paket ");
  303.             return c;
  304.             }
  305.          }
  306.       if (--length < 0) 
  307.       {
  308.          strcpy(v->Msgbuf, "zu langes Datenpaket ");
  309.          return ERROR;
  310.          }
  311.       ++v->Rxcount;
  312.       *buf++ = c;
  313.       crc = updcrc(c, crc);
  314.       continue;
  315.       }
  316.    }    /* End of short zrdata() */
  317.  
  318. /**********************************************************
  319.  *    short zrdat32(struct Vars *v, UBYTE *buf, short length)
  320.  *
  321.  * Receive array buf of max length with ending ZDLE sequence
  322.  * and CRC-32.  Returns the ending character or error code.
  323.  **********************************************************/
  324. int zrdat32(struct Vars *v, UBYTE *buf, short length)
  325. {
  326.    int c, d;
  327.    ULONG crc32;
  328.  
  329.    crc32 = 0xFFFFFFFFL;
  330.    v->Rxcount = 0;
  331.  
  332.    for (;;)
  333.    {
  334.       if ((c = zdlread(v)) & ~0xFF)
  335.       {
  336. crcfoo:
  337.          switch (c)
  338.      {
  339.          case GOTCRCE:
  340.          case GOTCRCG:
  341.          case GOTCRCQ:
  342.          case GOTCRCW:
  343.         d = c;
  344.         c &= 0xFF;
  345.             crc32 = UPDC32(c, crc32);
  346.             if ((c = zdlread(v)) & ~0xFF)
  347.            goto crcfoo;
  348.             crc32 = UPDC32(c, crc32);
  349.             if ((c = zdlread(v)) & ~0xFF)
  350.            goto crcfoo;
  351.             crc32 = UPDC32(c, crc32);
  352.             if ((c = zdlread(v)) & ~0xFF)
  353.            goto crcfoo;
  354.             crc32 = UPDC32(c, crc32);
  355.             if ((c = zdlread(v)) & ~0xFF)
  356.            goto crcfoo;
  357.             crc32 = UPDC32(c, crc32);
  358.         if (crc32 != 0xDEBB20E3)
  359.         {
  360.                strcpy(v->Msgbuf, "CRC-Fehler in Datenpaket");
  361.                return ERROR;
  362.                }
  363. #ifdef DEBUGLOG
  364.             mysprintf(v->Msgbuf, "zrdat32: cnt = %ld ret = %lx\n",
  365.            (long) v->Rxcount, (long) d);
  366.             dlog(v, v->Msgbuf);
  367. #endif
  368.             return d;
  369.          case GOTCAN:
  370.             strcpy(v->Msgbuf, "Sender hat abgebrochen ");
  371.             return ZCAN;
  372.          case TIMEOUT:
  373.             strcpy(v->Msgbuf, "Paket-Timeout ");
  374.             return c;
  375.          case RCDO:
  376.             return c;
  377.          default:
  378.             strcpy(v->Msgbuf, "Unbekanntes Paket ");
  379.             return c;
  380.             }
  381.          }
  382.       if (--length < 0) 
  383.       {
  384.          strcpy(v->Msgbuf, "zu langes Datenpaket ");
  385.          return ERROR;
  386.          }
  387.       ++v->Rxcount;
  388.       *buf++ = c;
  389.       crc32 = UPDC32(c, crc32);
  390.       continue;
  391.       }
  392.    }    /* End of short zrdat32() */
  393.  
  394. /**********************************************************
  395.  *    short zgethdr(struct Vars *v)
  396.  *
  397.  * Read a ZMODEM header to hdr, either binary or hex.
  398.  *  On success return type of header.
  399.  *  Otherwise return negative on error.
  400.  **********************************************************/
  401. int zgethdr(struct Vars *v)
  402. {
  403.    int c, cancount;
  404.    long n;
  405. #ifdef DEBUGLOG
  406.    UBYTE msgbuf [128];
  407. #endif
  408.  
  409.    n = 8192;   /* Max characters before start of frame */
  410.    cancount = 5;
  411. again:
  412.    v->Rxframeind = v->Rxtype = 0;
  413.    switch (c = noxrd7(v))
  414.    {
  415.    case RCDO:
  416.    case TIMEOUT:
  417.       goto fifi;
  418.    case CAN:
  419.       if (--cancount <= 0)
  420.       {
  421.          c = ZCAN;
  422.          goto fifi;
  423.          }
  424.    default:
  425. agn2:
  426.       if (--n <= 0)
  427.       {
  428.          strcpy(v->Msgbuf, "Entst÷rungsfehler ");
  429.          return ERROR;
  430.          }
  431.       if (c != CAN)
  432.      cancount = 5;
  433.       goto again;
  434.    case ZPAD:              /* This is what we want. */
  435.       break;
  436.       }
  437.    cancount = 5;
  438. splat:
  439.    switch (c = noxrd7(v))
  440.    {
  441.    case ZPAD:
  442.       goto splat;
  443.    case RCDO:
  444.    case TIMEOUT:
  445.       goto fifi;
  446.    default:
  447.       goto agn2;
  448.    case ZDLE:              /* This is what we want. */
  449.       break;
  450.       }
  451.  
  452.    switch (c = noxrd7(v))
  453.    {
  454.    case RCDO:
  455.    case TIMEOUT:
  456.       goto fifi;
  457.    case ZBIN:
  458.       v->Rxframeind = ZBIN;
  459.       v->Crc32 = FALSE;
  460.       c =  zrbhdr(v);
  461.       break;
  462.    case ZBIN32:
  463.       v->Crc32 = v->Rxframeind = ZBIN32;
  464.       c =  zrbhdr32(v);
  465.       break;
  466.    case ZHEX:
  467.       v->Rxframeind = ZHEX;
  468.       v->Crc32 = FALSE;
  469.       c =  zrhhdr(v);
  470.       break;
  471.    case CAN:
  472.       if (--cancount <= 0)
  473.       {
  474.          c = ZCAN;
  475.          goto fifi;
  476.          }
  477.       goto agn2;
  478.    default:
  479.       goto agn2;
  480.       }
  481.    v->Rxpos = rclhdr(v);
  482. fifi:
  483.    switch (c)
  484.    {
  485.    case GOTCAN:
  486.       c = ZCAN;
  487.    case ZNAK:
  488.    case ZCAN:
  489.    case ERROR:
  490.    case TIMEOUT:
  491.    case RCDO:
  492.       mysprintf(v->Msgbuf, "%s %s ", frametypes[c + FTOFFSET],
  493.          (c >= 0) ? "header" : "error");
  494. #ifdef DEBUGLOG
  495.    default:
  496.       if (c >= -3 && c <= FRTYPES)
  497.          mysprintf(msgbuf, "zgethdr: %s @ %ld\n", frametypes[c + FTOFFSET],
  498.         v->Rxpos);
  499.       else
  500.          mysprintf(msgbuf, "zgethdr: Unknown type %ld @ %ld\n", (long) c,
  501.         v->Rxpos);
  502.       dlog(v, msgbuf);
  503. #endif
  504.       }
  505.    return c;
  506.    }    /* End of short zgethdr() */
  507.  
  508. /**********************************************************
  509.  *    short zrbhdr(struct Vars *v)
  510.  *
  511.  * Receive a binary style header (type and position)
  512.  **********************************************************/
  513. int zrbhdr(struct Vars *v)
  514. {
  515.    UBYTE *hdr = v->Rxhdr;
  516.    int c, n;
  517.    USHORT crc;
  518.  
  519.    if ((c = zdlread(v)) & ~0xFF)
  520.       return c;
  521.    v->Rxtype = c;
  522.    crc = updcrc(c, 0);
  523.  
  524.    for (n = 4; --n >= 0; )
  525.    {
  526.       if ((c = zdlread(v)) & ~0xFF)
  527.      return c;
  528.       crc = updcrc(c, crc);
  529.       *hdr++ = c;
  530.       }
  531.    if ((c = zdlread(v)) & ~0xFF)
  532.       return c;
  533.    crc = updcrc(c, crc);
  534.    if ((c = zdlread(v)) & ~0xFF)
  535.       return c;
  536.    crc = updcrc(c, crc);
  537.    if (crc & 0xFFFF)
  538.    {
  539.       strcpy(v->Msgbuf, "CRC-Fehler in Header ");
  540.       return ERROR;
  541.       }
  542.    return v->Rxtype;
  543.    }    /* End of short zrbhdr() */
  544.  
  545. /**********************************************************
  546.  *    short zrbhdr32(struct Vars *v)
  547.  *
  548.  * Receive a binary style header (type and position) with
  549.  * 32 bit FCS
  550.  **********************************************************/
  551. int zrbhdr32(struct Vars *v)
  552. {
  553.    UBYTE *hdr = v->Rxhdr;
  554.    int c, n;
  555.    ULONG crc32;
  556.  
  557.    if ((c = zdlread(v)) & ~0xFF)
  558.       return c;
  559.    v->Rxtype = c;
  560.    crc32 = 0xFFFFFFFFL;
  561.    crc32 = UPDC32(c, crc32);
  562. #ifdef DEBUGLOG
  563.    mysprintf(v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  564.    dlog(v, v->Msgbuf);
  565. #endif
  566.  
  567.    for (n = 4; --n >= 0; )
  568.    {
  569.       if ((c = zdlread(v)) & ~0xFF)
  570.      return c;
  571.       crc32 = UPDC32(c, crc32);
  572.       *hdr++ = c;
  573. #ifdef DEBUGLOG
  574.       mysprintf(v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  575.       dlog(v, v->Msgbuf);
  576. #endif
  577.       }
  578.    for (n = 4; --n >= 0; )
  579.    {
  580.       if ((c = zdlread(v)) & ~0xFF)
  581.      return c;
  582.       crc32 = UPDC32(c, crc32);
  583. #ifdef DEBUGLOG
  584.       mysprintf(v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  585.       dlog(v, v->Msgbuf);
  586. #endif
  587.       }
  588.    if (crc32 != 0xDEBB20E3)
  589.    {
  590.       strcpy(v->Msgbuf, "CRC-Fehler in Header ");
  591.       return ERROR;
  592.       }
  593.    return v->Rxtype;
  594.    }    /* End of short zrbhdr32() */
  595.  
  596. /**********************************************************
  597.  *    short zrhhdr(struct Vars *v)
  598.  *
  599.  * Receive a hex style header (type and position)
  600.  **********************************************************/
  601. int zrhhdr(struct Vars *v)
  602. {
  603.    UBYTE *hdr = v->Rxhdr;
  604.    int c, n;
  605.    USHORT crc;
  606.  
  607.    if ((c = zgethex(v)) < 0)
  608.       return c;
  609.    v->Rxtype = c;
  610.    crc = updcrc(c, 0);
  611.  
  612.    for (n = 4; --n >= 0; )
  613.    {
  614.       if ((c = zgethex(v)) < 0)
  615.      return c;
  616.       crc = updcrc(c, crc);
  617.       *hdr++ = c;
  618.       }
  619.    if ((c = zgethex(v)) < 0)
  620.       return c;
  621.    crc = updcrc(c, crc);
  622.    if ((c = zgethex(v)) < 0)
  623.       return c;
  624.    crc = updcrc(c, crc);
  625.    if (crc & 0xFFFF)
  626.    {
  627.       strcpy(v->Msgbuf, "CRC-Fehler im Header ");
  628.       return ERROR;
  629.       }
  630.    if (readock(v, 1) == '\r')
  631.       readock(v, 1);        /* Throw away possible cr/lf */
  632.    return v->Rxtype;
  633.    }    /* End of short zrhhdr() */
  634.  
  635. /**********************************************************
  636.  *    void zputhex(struct Vars *v, UBYTE c)
  637.  *
  638.  * Send a byte as two hex digits
  639.  **********************************************************/
  640. void zputhex(struct Vars *v, UBYTE c)
  641. {
  642.    static char digits[] = "0123456789abcdef";
  643.  
  644.    sendline(v, digits[(c >> 4) & 0x0F]);
  645.    sendline(v, digits[c & 0x0F]);
  646.    }    /* End of void zputhex() */
  647.  
  648. /**********************************************************
  649.  *    void zsendline(struct Vars *v, UBYTE c)
  650.  *
  651.  * Send character c with ZMODEM escape sequence encoding.
  652.  * Escape ZDLE, real DLE, XON, XOFF, and CR following @ (Telenet net escape)
  653.  **********************************************************/
  654. void zsendline(struct Vars *v, UBYTE c)
  655. {
  656.    switch (DLE_actions[c])
  657.    {
  658.    case 2:
  659.       if (v->Lastzsent != '@')
  660.          goto sendit;
  661.       /* Fallthrough */
  662.    case 1:
  663.       xsendline(v, ZDLE);
  664.       c ^= 0x40;
  665. sendit:
  666.    case 0:
  667.       xsendline(v, v->Lastzsent = c);
  668.       }
  669.    }    /* End of void zsendline() */
  670.  
  671. /**********************************************************
  672.  *    short zgethex(struct Vars *v)
  673.  *
  674.  * Decode two lower case hex digits into an 8 bit byte value
  675.  **********************************************************/
  676. int zgethex(struct Vars *v)
  677. {
  678.    int c, n;
  679.  
  680.    if ((n = noxrd7(v)) < 0)
  681.       return n;
  682.    n -= '0';
  683.    if (n > 9)
  684.       n -= ('a' - ':');
  685.    if (n & ~0xF)
  686.       return ERROR;
  687.  
  688.    if ((c = noxrd7(v)) < 0)
  689.       return c;
  690.    c -= '0';
  691.    if (c > 9)
  692.       c -= ('a' - ':');
  693.    if (c & ~0xF)
  694.       return ERROR;
  695.  
  696.    return (n << 4 | c);
  697.    }    /* End of short zgethex() */
  698.  
  699. /**********************************************************
  700.  *    short zdlread(struct Vars *v)
  701.  *
  702.  * Read a byte, checking for ZMODEM escape encoding
  703.  * including CAN*5 which represents a quick abort.
  704.  **********************************************************/
  705. int zdlread(struct Vars *v)
  706. {
  707.    int c;
  708.  
  709.    if ((c = readock(v, v->Rxtimeout)) != ZDLE)
  710.       return c;
  711.    if ((c = readock(v, v->Rxtimeout)) < 0)
  712.       return c;
  713.    if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  714.       return c;
  715.    if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  716.       return c;
  717.    if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  718.       return c;
  719.    switch (c)
  720.    {
  721.    case CAN:
  722.       return GOTCAN;
  723.    case ZCRCE:
  724.    case ZCRCG:
  725.    case ZCRCQ:
  726.    case ZCRCW:
  727.       return (c | GOTOR);
  728.    case ZRUB0:
  729.       return 0x7F;
  730.    case ZRUB1:
  731.       return 0xFF;
  732.    default:
  733.       if ((c & 0x60) ==  0x40)
  734.      return (c ^ 0x40);
  735.       break;
  736.       }
  737.    strcpy(v->Msgbuf, "Falsche ZMODEM-ESC-Sequenz ");
  738.    return ERROR;
  739.    }    /* End of short zdlread() */
  740.  
  741. /**********************************************************
  742.  *    short noxrd7(struct Vars *v)
  743.  *
  744.  * Read a character from the modem line with timeout.
  745.  * Eat parity, XON and XOFF characters.
  746.  **********************************************************/
  747. int noxrd7(struct Vars *v)
  748. {
  749.    int c;
  750.  
  751.    for (;;)
  752.    {
  753.       if ((c = readock(v, v->Rxtimeout)) < 0)
  754.      return c;
  755.       switch (c &= 0x7F)
  756.       {
  757.       case XON:
  758.       case XOFF:
  759.          continue;
  760.       default:
  761.          return c;
  762.          }
  763.       }
  764.    }    /* short noxrd7() */
  765.  
  766. /**********************************************************
  767.  *    void stohdr(struct Vars *v, long pos)
  768.  *
  769.  * Store long integer pos in Txhdr
  770.  **********************************************************/
  771. void stohdr(struct Vars *v, long pos)
  772. {
  773.    v->Txhdr[ZP0] = pos;
  774.    pos >>= 8;
  775.    v->Txhdr[ZP1] = pos;
  776.    pos >>= 8;
  777.    v->Txhdr[ZP2] = pos;
  778.    pos >>= 8;
  779.    v->Txhdr[ZP3] = pos;
  780.    }    /* End of void stohdr() */
  781.  
  782. /**********************************************************
  783.  *    long rclhdr(struct Vars *v)
  784.  *
  785.  * Recover a long integer from a header
  786.  **********************************************************/
  787. long rclhdr(struct Vars *v)
  788. {
  789.    long l;
  790.  
  791.    l = v->Rxhdr[ZP3];
  792.    l = (l << 8) | v->Rxhdr[ZP2];
  793.    l = (l << 8) | v->Rxhdr[ZP1];
  794.    l = (l << 8) | v->Rxhdr[ZP0];
  795.    return l;
  796.    }    /* End of long rclhdr() */
  797. /* End of Zm.c source */
  798.