home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / ftp.vapor.com / microdot-1 / md1_src_02.lzx / zm_receive.c < prev    next >
C/C++ Source or Header  |  2014-05-19  |  17KB  |  588 lines

  1. /**********************************************************************
  2.  * Receive.c:  File reception routines for xprzmodem.library;
  3.  * Version 2.10, 12 February 1991, by Rick Huebner.
  4.  * Based closely on Chuck Forsberg's rz.c example ZModem code,
  5.  * but too pervasively modified to even think of detailing the changes.
  6.  * Released to the Public Domain; do as you like with this code.
  7.  *
  8.  * Version 2.50, 15 November 1991, CRC-32 additions by William M. Perkins.
  9.  **********************************************************************/
  10.  
  11. /*#include <proto/all.h>
  12. #include <exec/types.h>
  13. #include <ctype.h>
  14. #include <stdio.h>*/
  15. #include <stdlib.h>
  16. #include <string.h>
  17.  
  18. #include "xproto.h"
  19. #include "zmodem.h"
  20. #include "xprzmodem.h"
  21.  
  22. #ifdef DEBUGLOG
  23. extern void *DebugLog;
  24. #endif
  25.  
  26. /* Proto fⁿr Inlines */
  27.  
  28. static short rcvbatch(struct Vars *v);
  29. static short tryz(struct Vars *v);
  30. static short rzfiles(struct Vars *v);
  31. static short rzfile(struct Vars *v);
  32. static short procheader(struct Vars *v);
  33. static short putsec(struct Vars *v);
  34. static void  ackbibi(struct Vars *v);
  35.  
  36. /**********************************************************
  37.  *    long XProtocolReceive(struct XPR_IO *xio)
  38.  *
  39.  * Main file reception routine; called by comm program
  40.  **********************************************************/
  41. long XProtocolReceive(struct XPR_IO *xio)
  42. {
  43.    struct SetupVars *sv;
  44.    struct Vars *v;
  45.    UBYTE err = FALSE;
  46.  
  47.    /* Perform common setup and initializations */
  48.    if (! (v = setup(xio)))
  49.       return XPRS_FAILURE;
  50.    v->Tryzhdrtype = ZRINIT;
  51.    v->Rxtimeout = 100;
  52.  
  53.    sv = (void *) v->io.xpr_data;
  54.    if (sv->bufpos)
  55.    {
  56.       v->Modemchar = v->Modembuf;
  57.       if (sv->buflen > sizeof(v->Modembuf))
  58.      sv->buflen = sizeof(v->Modembuf);
  59.       memcpy(v->Modembuf, sv->bufpos,sv->buflen);
  60.       v->Modemcount = sv->buflen;
  61.       }
  62.  
  63.    /* Transfer the files */  
  64.    if (rcvbatch(v) == ERROR)
  65.    {
  66.       upderr(v, "Empfang abgebrochen oder Timeout!");
  67.       err = TRUE;
  68.       }
  69.    else
  70.       updmsg(v, "▄bertragung erfolgreich beendet.");
  71.  
  72.    FreeMem(v, (long) sizeof(struct Vars));
  73.  
  74. #ifdef DEBUGLOG
  75.    if (DebugLog)
  76.    {
  77.       xpr_fclose(&v->io, DebugLog);
  78.       DebugLog = NULL;
  79.       }
  80. #endif
  81.  
  82.    return (err) ? XPRS_FAILURE : XPRS_SUCCESS;
  83.    }    /* End of long XProtocolReceive() */
  84.  
  85. /**********************************************************
  86.  *    short rcvbatch(struct Vars *v)
  87.  *
  88.  * Start the batch transfer
  89.  **********************************************************/
  90. static short rcvbatch(struct Vars *v)
  91. {
  92.    switch (tryz(v))
  93.    {
  94.    case ZCOMPL:
  95.       return OK;
  96.    case ZFILE:
  97.       if (rzfiles(v) == OK)
  98.      return OK;
  99.       }
  100.    canit(v);
  101.    return ERROR;
  102.    }    /* End of short rcvbatch() */
  103.  
  104. /**********************************************************
  105.  *    short tryz(struct Vars *v)
  106.  *
  107.  * Negotiate with sender to start a file transfer
  108.  **********************************************************/
  109. static short tryz(struct Vars *v)
  110. {
  111.    short n, errors = 0;
  112.  
  113.    for (n = v->ErrorLimit; --n >= 0; )
  114.    {
  115.       /* Set max frame length and capability flags */
  116.       stohdr(v, (long) v->Tframlen);
  117.       v->Txhdr[ZF0] = CANFC32 | CANFDX | CANOVIO;
  118.       zshhdr(v, v->Tryzhdrtype);
  119.       sendbuf(v);
  120. again:
  121.       /* Check for abort from comm program */
  122.       if (xpr_chkabort())
  123.          return ERROR;
  124.       switch (zgethdr(v))
  125.       {
  126.       case ZFILE:    /* File name and info packet */
  127.          v->Zconv  = v->Rxhdr[ZF0];  /* Suggested txt mode; ZCNL = text, */
  128.                      /* ZCBIN = binary, 0 = don't know. */
  129.          v->Zmanag = v->Rxhdr[ZF1];  /* Suggested file management mode. */
  130.          v->Ztrans = v->Rxhdr[ZF2];  /* Suggested file transport mode. */
  131.          v->Tryzhdrtype = ZRINIT;
  132.          if (zrdata(v, v->Pktbuf, KSIZE) == GOTCRCW)
  133.         return ZFILE;
  134.          zshhdr(v, ZNAK);   /* Packet mangled, ask for retry */
  135.          sendbuf(v);
  136.          goto again;
  137.       case ZSINIT:   /* Special attention-grabbing string to use to */
  138.              /* interrupt sender */
  139.          if (zrdata(v, v->Attn, ZATTNLEN) == GOTCRCW)
  140.             zshhdr(v, ZACK);
  141.          else
  142.             zshhdr(v, ZNAK);
  143.          sendbuf(v);
  144.          goto again;
  145.       case ZFREECNT: /* Sender wants to know how much room we've got */
  146.          stohdr(v, getfree());
  147.          zshhdr(v, ZACK);
  148.          sendbuf(v);
  149.          goto again;
  150.       case ZCOMMAND: /* Sender wants us to do remote commands, */
  151.              /* but we don't do requests. */
  152.          if (zrdata(v, v->Pktbuf, KSIZE) == GOTCRCW)
  153.      {
  154.             mysprintf(v->Msgbuf, "Kommando %s ignoriert!", v->Pktbuf);
  155.             upderr(v, v->Msgbuf); /* Ignore and report all uploaded commands */
  156.             stohdr(v, 0L);        /* whilst telling sender they worked; */
  157.             do
  158.         {
  159.                zshhdr(v, ZCOMPL); /* paranoia can be good for you... */
  160.                sendbuf(v);
  161.                }
  162.         while (++errors < v->ErrorLimit && zgethdr(v) != ZFIN);
  163.             ackbibi(v);
  164.             return ZCOMPL;
  165.             }
  166.      else
  167.             zshhdr(v, ZNAK);
  168.          sendbuf(v);
  169.          goto again;
  170.       case ZCOMPL:
  171.          goto again;
  172.       case ZFIN:    /* Sender has ended batch */
  173.          ackbibi(v);
  174.          return ZCOMPL;
  175.       case ZCAN:
  176.       case RCDO:
  177.          upderr(v, v->Msgbuf);
  178.          return ERROR;
  179.          }
  180.       }
  181.    return ERROR;
  182.    }    /* End of short tryz() */
  183.  
  184. /**********************************************************
  185.  *    short rzfiles(struct Vars *v)
  186.  *
  187.  * Receive a batch of files
  188.  **********************************************************/
  189. static short rzfiles(struct Vars *v)
  190. {
  191.    short c;
  192.  
  193.    /* Keep receiving files until end of batch or error */
  194.    while (TRUE)
  195.    {
  196.       switch (c = rzfile(v))
  197.       {
  198.       case ZEOF:
  199.       case ZSKIP:
  200.          switch (tryz(v))
  201.      {
  202.          case ZCOMPL:
  203.             return OK;
  204.          default:
  205.             return ERROR;
  206.          case ZFILE:
  207.             break;
  208.             }
  209.          break;
  210.       default:
  211.          bfclose(v);
  212.         updmsg(v, "Datei nur teilweise empfangen!");
  213.          return c;
  214.          }
  215.       }
  216.    }    /* End of short rzfiles() */
  217.  
  218. /**********************************************************
  219.  *    short rzfile(struct Vars *v)
  220.  *
  221.  * Receive one file; file name packet already read into
  222.  * Pktbuf by tryz()
  223.  **********************************************************/
  224. static short rzfile(struct Vars *v)
  225. {
  226.    short c, n;
  227.  
  228.    /*
  229.     * Process file name packet; either open file and prepare to receive,
  230.     * or tell us to skip this one.
  231.     */
  232.    if (procheader(v) == ERROR)
  233.       return v->Tryzhdrtype = ZSKIP;
  234.  
  235.    n = v->ErrorLimit;
  236.    v->Rxbytes = v->Strtpos;
  237.    v->Eofseen = FALSE;
  238.  
  239.    /* Receive ZDATA frames until finished */
  240.    while (TRUE)
  241.    {
  242.       stohdr(v, v->Rxbytes);      /* Tell sender where to start frame */
  243.       zshhdr(v, ZRPOS);
  244.       sendbuf(v);
  245. nxthdr:
  246.       /* Check for abort from comm program */
  247.       if (xpr_chkabort())
  248.          return ERROR;
  249.       switch (c = zgethdr(v))    /* Wait for frame header */
  250.       {
  251.       default:
  252. #ifdef DEBUGLOG
  253.          mysprintf(v->Msgbuf, "rzfile: zgethdr returned %ld\n", (long) c);
  254.          dlog(v, v->Msgbuf);
  255. #endif
  256.          return ERROR;
  257.       case ZNAK:
  258.       case TIMEOUT:
  259.          if (--n < 0)
  260.         return ERROR;
  261. #ifdef DEBUGLOG
  262.          dlog(v, "rzfile: zgethdr NAK/Timeout\n");
  263. #endif
  264.          v->xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_TIMEOUTS;
  265.          mysprintf(strchr(v->Msgbuf, '\0'), "@ %ld; noch %ld Versuche",
  266.         v->Rxbytes, (long) n);
  267.          v->xpru.xpru_errormsg = (char *) v->Msgbuf;
  268.          ++v->xpru.xpru_timeouts;
  269.          xpr_update(&v->xpru);
  270.          continue;
  271.       case ZFILE:     /* Sender didn't see our ZRPOS yet; try again */
  272.          zrdata(v, v->Pktbuf, KSIZE);   /* Read and discard redundant */
  273.      continue;            /* filename packet */
  274.       case ZEOF:      /* End of file data */
  275.          if (v->Rxpos != v->Rxbytes)    /* We aren't in sync; go back */
  276.      {
  277.             mysprintf(v->Msgbuf, "Falsches EOF: hier @%ld, Sender @%ld!",
  278.            v->Rxbytes, v->Rxpos);
  279.             upderr(v, v->Msgbuf);
  280.             continue;
  281.             }
  282.          bfclose(v);  /* All done; close file */
  283. #ifdef DEBUGLOG
  284.          dlog(v, "rzfile: EOF\n");
  285. #endif
  286.          updmsg(v, "EOF empfangen; warte auf nΣchste Datei.");
  287.          return c;
  288.       case ERROR:     /* Too much garbage while waiting for frame header */
  289.          if ( --n < 0)
  290.         return ERROR;
  291. #ifdef DEBUGLOG
  292.          dlog(v, "rzfile: zgethdr garbage overflow\n");
  293. #endif
  294.          v->xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_ERRORS;
  295.          mysprintf(strchr(v->Msgbuf, '\0'), "@ %ld; noch %ld Versuche",
  296.         v->Rxbytes, (long) n);
  297.          v->xpru.xpru_errormsg = (char *) v->Msgbuf;
  298.          ++v->xpru.xpru_errors;
  299.          xpr_update(&v->xpru);
  300.          zmputs(v, v->Attn);
  301.          xpr_sflush();
  302.          v->Modemcount = 0;
  303.          continue;
  304.       case ZDATA:     /* More file data packets forthcoming */
  305.          if (v->Rxpos != v->Rxbytes)     /* We aren't in sync; go back */
  306.      {
  307.             if ( --n < 0)
  308.            return ERROR;
  309.             v->xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_ERRORS;
  310.             mysprintf(v->Msgbuf, "Synchronisationsfehler: hier @%ld, Sender @%ld!",
  311.            v->Rxbytes, v->Rxpos);
  312.             v->xpru.xpru_errormsg = (char *) v->Msgbuf;
  313.             ++v->xpru.xpru_errors;
  314.             xpr_update(&v->xpru);
  315.  
  316.             // flushen
  317.             v->Modemcount = 0;
  318.             zmputs(v, v->Attn);
  319.             xpr_sflush();
  320.  
  321.             continue;
  322.             }
  323.          /* Receive file data packet(s) */
  324. moredata:
  325.          /* Check for abort from comm program */
  326.          if (xpr_chkabort())
  327.         goto aborted;
  328.          switch (c = zrdata(v, v->Pktbuf,KSIZE))
  329.      {
  330.      case ZCAN:
  331.          case RCDO:
  332. aborted:
  333. #ifdef DEBUGLOG
  334.             dlog(v, "rzfile: zrdata returned CAN\n");
  335. #endif
  336.             upderr(v, "▄bertragung abgebrochen!");
  337.             return ERROR;
  338.          case ERROR:     /* CRC error or packet too long */
  339.             if ( --n < 0)
  340.            return ERROR;
  341. #ifdef DEBUGLOG
  342.             dlog(v, "rzfile: zrdata returned error\n");
  343. #endif
  344.             v->xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_ERRORS;
  345.             mysprintf(strchr(v->Msgbuf, '\0'), "@ %ld; noch %ld Versuche",
  346.            v->Rxbytes, (long) n);
  347.             v->xpru.xpru_errormsg = (char *) v->Msgbuf;
  348.             ++v->xpru.xpru_errors;
  349.             xpr_update(&v->xpru);
  350. #ifdef DEBUGLOG
  351.             dlog(v, v->Msgbuf);
  352.             dlog(v, "\n");
  353. #endif
  354.             zmputs(v, v->Attn);
  355.             continue;
  356.          case TIMEOUT:
  357.             if ( --n < 0)
  358.            return ERROR;
  359. #ifdef DEBUGLOG
  360.             dlog(v, "rzfile: zrdata returned timeout\n");
  361. #endif
  362.             v->xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_TIMEOUTS;
  363.             mysprintf(strchr(v->Msgbuf, '\0'), "@ %ld; noch %ld Versuche",
  364.            v->Rxbytes, (long) n);
  365.             v->xpru.xpru_errormsg = (char *) v->Msgbuf;
  366.             ++v->xpru.xpru_timeouts;
  367.             xpr_update(&v->xpru);
  368. #ifdef DEBUGLOG
  369.             dlog(v, v->Msgbuf);
  370.             dlog(v, "\n");
  371. #endif
  372.             continue;
  373.          case GOTCRCW:   /* Sender says it's waiting for an ACK */
  374.             n = v->ErrorLimit;
  375.             if (putsec(v) == ERROR)
  376.            return ERROR;
  377.             stohdr(v, v->Rxbytes);
  378.             zshhdr(v, ZACK);
  379.             sendbuf(v);
  380.             goto nxthdr;
  381.          case GOTCRCQ:   /* Sender says it's not waiting, */
  382.              /* but ACK anyway (rarely used) */
  383.             n = v->ErrorLimit;
  384.             if (putsec(v) == ERROR)
  385.            return ERROR;
  386.             stohdr(v, v->Rxbytes);
  387.             zshhdr(v, ZACK);
  388.             sendbuf(v);
  389.             goto moredata;
  390.          case GOTCRCG:   /* Sender says keep receiving, there's more coming */
  391.             n = v->ErrorLimit;
  392.             if (putsec(v) == ERROR)
  393.            return ERROR;
  394.             goto moredata;
  395.          case GOTCRCE:   /* Sender says this is the last packet */
  396.             n = v->ErrorLimit;
  397.             if (putsec(v) == ERROR)
  398.            return ERROR;
  399.             goto nxthdr;
  400.             }
  401.          }
  402.       }
  403.    }    /* End of short rzfile() */
  404.  
  405. /**********************************************************
  406.  *    short procheader(struct Vars *v)
  407.  *
  408.  * Process file name & info packet; either open file and
  409.  * prepare to receive, or return ERROR if we should skip
  410.  * this one for some reason
  411.  **********************************************************/
  412. static short procheader(struct Vars *v)
  413. {
  414.    UBYTE *p, *openmode;
  415.  
  416.    openmode = "w";
  417.    v->Strtpos = 0;
  418.  
  419.    /* Extract expected filesize from file info packet, if given */
  420.    v->Fsize = -1;
  421.    p = strchr(v->Pktbuf, '\0') + 1;
  422.    if (*p)
  423.       v->Fsize = atol(p);
  424.    /*
  425.     * Make sure we have room for file; skip it if not.
  426.     * Commented out for now, since getfree() isn't implemented yet.
  427.    if (v->Fsize > getfree())
  428.    {
  429.       mysprintf(v->Msgbuf, "Insufficient disk space; need %ld bytes, have %ld",
  430.      v->Fsize, getfree());
  431.       upderr(v, v->Msgbuf);
  432.       v->Noroom = TRUE;
  433.       return ERROR;
  434.       }
  435.    */
  436.  
  437.      /* else use the default directory path specified in the setup options */
  438.       p = strchr(v->Pktbuf, '\0'); /* start at end and scan back */
  439.                    /* to start of name */
  440.       while (p >= v->Pktbuf && *p != '/' && *p != '\\' && *p != ':')
  441.      --p;
  442.       strcpy(v->Filename, ++p);
  443.  
  444.    /* Display name of file being received for user */
  445.    v->xpru.xpru_updatemask = XPRU_FILENAME;
  446.    v->xpru.xpru_filename = (char *) v->Filename;
  447.    xpr_update(&v->xpru);
  448.  
  449.    /*
  450.     * If a file with this name already exists, handle in
  451.     * accordance with O option
  452.     */
  453.    if (exist(v))
  454.    {
  455.          openmode = "a";
  456.          v->Strtpos = xpr_finfo(v->Filename, 1L);
  457.       }
  458.  
  459.    /* Set text/binary mode according to options before opening file */
  460.    set_textmode(v);
  461.  
  462.    /*
  463.     * Figure out file translation mode to use; either binary (verbatim
  464.     * transfer) or ASCII (perform end-of-line conversions).  If user has
  465.     * specified a mode (TY or TN), that's what we use.  If user says use
  466.     * sender's suggestion (T?), set mode according to Zconv flag.  If neither
  467.     * side specifies, default to binary mode.
  468.     */
  469.    v->Thisbinary =  v->Rxbinary || !v->Rxascii;
  470.    if (! v->Rxbinary && v->Zconv == ZCNL)
  471.       v->Thisbinary = FALSE;
  472.    if (! v->Rxascii && v->Zconv == ZCBIN)
  473.       v->Thisbinary = TRUE;
  474.  
  475.    /* Open the file (finally) */
  476.    if (! (v->File = bfopen(v, openmode)))
  477.    {
  478.       ++v->Errcnt;
  479.       upderr(v, "Kann Datei nicht ÷ffnen!");
  480.       return ERROR;
  481.       }
  482.    getsystime(&v->Starttime);
  483.  
  484.    /* Initialize comm program transfer status display */
  485.    v->xpru.xpru_updatemask = XPRU_PROTOCOL | XPRU_FILESIZE | XPRU_MSG 
  486.       | XPRU_BLOCKS | XPRU_ERRORS | XPRU_TIMEOUTS | XPRU_BLOCKCHECK
  487.       | XPRU_BYTES | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME| XPRU_DATARATE;
  488.    v->xpru.xpru_protocol = "ZModem";
  489.    v->xpru.xpru_filesize = v->Fsize;
  490.    v->xpru.xpru_msg = "Empfange Datei...";
  491.    v->xpru.xpru_blocks = v->xpru.xpru_errors = v->xpru.xpru_timeouts = 0;
  492.    v->xpru.xpru_blockcheck = v->Crc32 ? "CRC-32" : "CRC-16";
  493.    v->xpru.xpru_bytes = v->Strtpos;
  494.    update_rate(v);
  495.    xpr_update(&v->xpru);
  496.  
  497.    return OK;
  498.    }    /* End of short procheader() */
  499.  
  500. /**********************************************************
  501.  *    short putsec(struct Vars *v)
  502.  *
  503.  * Writes the received file data to the output file.
  504.  * If in ASCII mode, stops writing at first ^Z, and converts all
  505.  * \r\n pairs or solo \r's to \n's.
  506.  **********************************************************/
  507. static short putsec(struct Vars *v)
  508. {
  509.    static char nl = '\n';
  510.    UBYTE *p;
  511.    short n;
  512.  
  513.    /* If in binary mode, write it out verbatim */
  514.    if (v->Thisbinary)
  515.    {
  516.       if (bfwrite(v, v->Pktbuf, (long) v->Rxcount) != v->Rxcount)
  517.      goto diskfull;
  518.       /* If in text mode, perform end-of-line cleanup */
  519.       }
  520.    else
  521.    {
  522.       if (v->Eofseen)
  523.      return OK;
  524.       for (p = v->Pktbuf, n = v->Rxcount; --n >= 0; ++p)
  525.       {
  526.      if (*p == CPMEOF)
  527.      {
  528.             v->Eofseen = TRUE;
  529.             return OK;
  530.         }
  531.      else if (*p != '\n' && v->Lastsent == '\r')
  532.      {
  533.             if (bfwrite(v, &nl, 1L) != 1)
  534.            goto diskfull;
  535.             }  
  536.          if (*p != '\r' && bfwrite(v, p, 1L) != 1)
  537.         goto diskfull;
  538.      v->Lastsent = *p;
  539.      }
  540.       }
  541.  
  542.    /* Update comm program status display */
  543.    v->xpru.xpru_updatemask = XPRU_BLOCKS | XPRU_BLOCKSIZE | XPRU_BYTES
  544.       | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE | XPRU_BLOCKCHECK;
  545.    ++v->xpru.xpru_blocks;
  546.    v->xpru.xpru_blocksize = v->Rxcount;
  547.    v->xpru.xpru_bytes = v->Rxbytes += v->Rxcount;
  548.    v->xpru.xpru_blockcheck = v->Crc32 ? "CRC-32" : "CRC-16";
  549.    update_rate(v);
  550.    xpr_update(&v->xpru);
  551.  
  552.    return OK;
  553.  
  554. diskfull:
  555.    upderr(v, "Fehler beim Schreiben in die Datei!");
  556.    v->Noroom = TRUE;
  557.    return ERROR;
  558.    }    /* End of short putsec() */
  559.  
  560. /**********************************************************
  561.  *    void ackbibi(struct Vars *v)
  562.  *
  563.  * End of batch transmission; disengage cleanly from sender
  564.  **********************************************************/
  565. static void ackbibi(struct Vars *v)
  566. {
  567.    short n;
  568.  
  569. #ifdef DEBUGLOG
  570.    dlog(v, "ackbibi:\n");
  571. #endif
  572.    stohdr(v, 0L);
  573.    for (n = 4; --n; )
  574.    {
  575.       zshhdr(v, ZFIN);
  576.       sendbuf(v);
  577.       switch (readock(v, 100))
  578.       {
  579.       case 'O':
  580.          readock(v, 1);    /* Discard 2nd 'O' */
  581.       case TIMEOUT:
  582.       case RCDO:
  583.          return;
  584.          }
  585.       }
  586.    }    /* End of void ackbibi() */
  587. /* End of Receive.c source */
  588.