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

  1. /**********************************************************************
  2.  * Send.c: File transmission routines for xprzmodem.library;
  3.  * Original Version 2.10, 12 February 1991, by Rick Huebner.
  4.  * Based closely on Chuck Forsberg's sz.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.  * Version 2.51 29, January 1992, RX_timout fix by John Tillema
  10.  * Version 2.52   6 March 1992, Very minor fix with compiled 020 library
  11.  *               by William M. Perkins.
  12.  *
  13.  **********************************************************************/
  14.  
  15. /*#include <proto/all.h>
  16. #include <exec/types.h>
  17. #include <ctype.h>
  18. #include <stdio.h>*/
  19.  
  20. #include <string.h>
  21.  
  22. #include "xproto.h"
  23. #include "zmodem.h"
  24. #include "xprzmodem.h"
  25.  
  26. #ifdef DEBUGLOG
  27. extern void *DebugLog;
  28. #endif
  29.  
  30. /* Proto fⁿr Inlines */
  31.  
  32. static short getzrxinit(struct Vars *v);
  33. static void  sendbatch(struct Vars *v);
  34. static short sendone(struct Vars *v);
  35. static short sendname(struct Vars *v);
  36. static short zsendfile(struct Vars *v, short blen);
  37. static short zsendfdata(struct Vars *v);
  38. static short getinsync(struct Vars *v);
  39. static void  saybibi(struct Vars *v);
  40.  
  41.  
  42. /**********************************************************
  43.  *    long XProtocolSend(struct XPR_IO *xio)
  44.  *
  45.  * Main file transmission routine; called by comm program
  46.  **********************************************************/
  47. long XProtocolSend(struct XPR_IO *xio)
  48. {
  49.    struct Vars *v;
  50.    short err;
  51.  
  52.    /* Perform common setup and initializations */
  53.    if (! (v = setup(xio)) )
  54.       return XPRS_FAILURE;
  55.  
  56. /*  was 600, set to 300 to fix so it uploads correctly */
  57.    v->Rxtimeout = 300;
  58.    v->Wantfcs32 = TRUE;
  59.    v->Rxflags = 0;
  60.  
  61.    /* Transfer the files */  
  62.    zmputs(v, "rz\r");
  63.    stohdr(v, 0L);
  64.    zshhdr(v, ZRQINIT);
  65.    sendbuf(v);
  66.    if (getzrxinit(v) == ERROR) {
  67.     err=TRUE;
  68.       upderr(v, "Senden abgebrochen oder Timeout!");
  69.    }
  70.    else
  71.       sendbatch(v);
  72.  
  73.    /* Clean up and return */
  74.    if (err = v->Errcnt) {
  75.     err=TRUE;
  76.       upderr(v, "Datei(en) wegen ▄bertragunsfehlern ⁿbersprungen!");
  77.    }
  78.    else
  79.       updmsg(v, "▄bertragung erfolgreich beendet.");
  80.    FreeMem(v, (long) sizeof(struct Vars));
  81.   
  82.    return (err) ? XPRS_FAILURE : XPRS_SUCCESS;
  83.    }    /* End of long XProtocolSend() */
  84.  
  85. /**********************************************************
  86.  *    short getzrxinit(struct Vars *v)
  87.  *
  88.  * Negotiate with receiver to start a file transfer
  89.  **********************************************************/
  90. static short getzrxinit(struct Vars *v)
  91. {
  92.    short n;
  93.  
  94.    for (n = v->ErrorLimit; --n >= 0; )
  95.    {
  96.       /* Check for abort from comm program */
  97.       if (xpr_chkabort())
  98.          return ERROR;
  99.       switch (zgethdr(v))
  100.       {
  101.       case ZCHALLENGE:        /* Echo receiver's challenge number */
  102.          stohdr(v, v->Rxpos);
  103.          zshhdr(v, ZACK);
  104.          sendbuf(v);
  105.          continue;
  106.       case ZCOMMAND:          /* They didn't see our ZRQINIT; try again */
  107.          stohdr(v, 0L);
  108.          zshhdr(v, ZRQINIT);
  109.          sendbuf(v);
  110.          continue;
  111.       case ZRINIT:            /* Receiver ready; get transfer parameters */
  112.      v->Rxflags = 0xFF & v->Rxhdr[ZF0];
  113.      v->Txfcs32 = (v->Wantfcs32 && (v->Rxflags & CANFC32));
  114.          v->Rxbuflen = ((USHORT) v->Rxhdr[ZP1] << 8) | v->Rxhdr[ZP0];
  115. #ifdef DEBUGLOG
  116.          mysprintf(v->Msgbuf, "Txfcs32=%ld Rxbuflen=%ld Tframlen=%ld\n",
  117.         (long) v->Txfcs32, (long) v->Rxbuflen, (long) v->Tframlen);
  118.          dlog(v, v->Msgbuf);
  119. #endif
  120.          /* Use shortest of the two side's max frame lengths */
  121.          if (v->Tframlen && (! v->Rxbuflen || v->Tframlen < v->Rxbuflen))
  122.             v->Rxbuflen = v->Tframlen;
  123. #ifdef DEBUGLOG
  124.          mysprintf(v->Msgbuf, "Rxbuflen=%ld\n", (long) v->Rxbuflen);
  125.          dlog(v, v->Msgbuf);
  126. #endif
  127.          return OK;
  128.       case ZCAN:
  129.       case RCDO:
  130.       case TIMEOUT:
  131.          upderr(v, v->Msgbuf);
  132.          return ERROR;
  133.       case ZRQINIT:
  134.          if (v->Rxhdr[ZF0] == ZCOMMAND)
  135.         continue;
  136.          /* fallthrough... */
  137.       default:
  138.          zshhdr(v, ZNAK);
  139.          sendbuf(v);
  140.          continue;
  141.          }
  142.       }
  143.    return ERROR;
  144.    }    /* End of short getzrxinit() */
  145.  
  146. /**********************************************************
  147.  *    void sendbatch(struct Vars *v)
  148.  *
  149.  * Send a batch of files
  150.  **********************************************************/
  151. static void sendbatch(struct Vars *v)
  152. {
  153.    UBYTE single, done = FALSE;
  154.    long fstate;
  155.  
  156.      single = FALSE;
  157.      fstate = xpr_ffirst(v->Filename, v->io.xpr_filename);
  158.       if (! fstate)
  159.       {
  160.          upderr(v, "Keine Dateien gefunden.");
  161.          return;
  162.          }
  163.  
  164.    /* If using templates, keep getting names & sending until done */
  165.    while (! done)
  166.    {
  167.       if (sendone(v) == ERROR)
  168.      return;
  169.       if (single)
  170.      break;
  171.       fstate = xpr_fnext(fstate, v->Filename, v->io.xpr_filename);
  172.       done = ! fstate;
  173.       }
  174.  
  175.    /* End batch and return; if we never got started, just cancel receiver */
  176.    if (v->Filcnt)
  177.       saybibi(v);
  178.    else
  179.       canit(v);
  180.    }    /* End of void sendbatch() */
  181.  
  182. /**********************************************************
  183.  *    short sendone(struct Vars *v)
  184.  *
  185.  * Send the file named in v->Filename
  186.  **********************************************************/
  187. static short sendone(struct Vars *v)
  188. {
  189.    struct SetupVars *sv;
  190.  
  191. #ifdef DEBUGLOG
  192.    mysprintf(v->Msgbuf, "*** Sending %s\n", v->Filename);
  193.    dlog(v, v->Msgbuf);
  194. #endif
  195.  
  196.    /* Display name of file being sent for user */
  197.    v->xpru.xpru_updatemask = XPRU_FILENAME;
  198.    v->xpru.xpru_filename = v->Filename;
  199.    xpr_update(&v->xpru);
  200.  
  201.    /* Set text/binary mode according to options before opening file */
  202.    set_textmode(v);
  203.  
  204.    /* Open the file, if possible */
  205.    if (! (v->File = bfopen(v, "r")))
  206.    {
  207.       ++v->Errcnt;
  208.       upderr(v, "Kann Datei nicht ÷ffnen (wird ⁿbersprungen)");
  209.       return OK;      /* pass over it, there may be others */
  210.       }
  211.    ++v->Filcnt;
  212.    getsystime(&v->Starttime);
  213.  
  214.    /* Kick off the file transfer */
  215.    sv = (void *) v->io.xpr_data;
  216.    switch (sendname(v))
  217.    {
  218.    case ERROR:
  219.       ++v->Errcnt;
  220.       return ERROR;
  221.    case OK:
  222.       bfclose(v);
  223.       break;
  224.       }
  225.    return OK;
  226.    }    /* End of short sendone() */
  227.  
  228. /**********************************************************
  229.  *    short sendname(struct Vars *v)
  230.  *
  231.  * Build file info block consisting of file name, length,
  232.  * time, and mode
  233.  **********************************************************/
  234. static short sendname(struct Vars *v)
  235. {
  236.    UBYTE *p, *q, buff [32];
  237.  
  238.    /* Initialize comm program transfer status display */
  239.    v->Fsize = xpr_finfo(v->Filename, 1L);
  240.    v->xpru.xpru_updatemask = XPRU_PROTOCOL | XPRU_FILESIZE | XPRU_MSG
  241.       | XPRU_BLOCKS | XPRU_ERRORS | XPRU_TIMEOUTS | XPRU_BLOCKCHECK
  242.       | XPRU_BYTES | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE;
  243.    v->xpru.xpru_protocol = "ZModem";
  244.    v->xpru.xpru_filesize = v->Fsize;
  245.    v->xpru.xpru_msg = "Sende Datei...";
  246.    v->xpru.xpru_blocks = v->xpru.xpru_errors = v->xpru.xpru_timeouts = 0;
  247.    v->xpru.xpru_blockcheck = v->Crc32t ? "CRC-32" : "CRC-16";
  248.    v->xpru.xpru_bytes = v->Strtpos = 0;
  249.    update_rate(v);
  250.    xpr_update(&v->xpru);
  251.  
  252.    /*sv = (void *) xpr_data;*/
  253.    /* extract outgoing file name without directory path */
  254.    for (p = v->Filename, q = v->Pktbuf ; *p; ++p, ++q)
  255.      if ((*q = *p) == '/' || *q == ':')
  256.        q = v->Pktbuf - 1;
  257.       *q = '\0';
  258.       p = ++q;
  259.  
  260.    /* Zero out remainder of file info packet */
  261.    memset(p, 0, sizeof(v->Pktbuf) - (p - v->Pktbuf));
  262.  
  263.    /* Store file size, timestamp, and mode in info packet */
  264.    /*
  265.     * XPR spec doesn't provide a way to get the file timestamp or file mode,
  266.     * so we'll just fake it with the current time and a dummy 0.
  267.     */
  268.    stcl_o(buff, getsystime(NULL) + UnixTimeOffset);
  269.    /* amiga.lib mysprintf() can't do %lo format, so we do it the hard way */
  270.    /* Yes, octal; ZModem was originally done on Unix, and they like octal there */
  271.    mysprintf(p, "%ld %s 0", (v->Fsize < 0) ? 0L : v->Fsize,buff);
  272.  
  273.    /* Send filename packet */
  274.    return zsendfile(v, (short) (p - v->Pktbuf + strlen(p) + 1));
  275.    }    /* End of short sendname() */
  276.  
  277. /**********************************************************
  278.  *    short zsendfile(struct Vars *v, short blen)
  279.  *
  280.  * Send the filename packet and see if receiver will accept
  281.  * file
  282.  **********************************************************/
  283. static short zsendfile(struct Vars *v, short blen)
  284. {
  285.    short c;
  286.  
  287.    while (TRUE)
  288.    {
  289.       v->Txhdr[ZF0] = v->Lzconv; /* Text or Binary mode; from config string */
  290.       v->Txhdr[ZF1] = LZMANAG;   /* Default file management mode */
  291.       v->Txhdr[ZF2] = LZTRANS;   /* Default file transport mode */
  292.       v->Txhdr[ZF3] = 0;
  293.       zsbhdr(v, ZFILE);
  294.       zsdata(v, blen, ZCRCW);
  295.       sendbuf(v);
  296. again:
  297.       /* Check for abort from comm program */
  298.       if (xpr_chkabort())
  299.       {
  300.          bfclose(v);
  301.          return ERROR;
  302.          }
  303.       switch (c = zgethdr(v))
  304.       {
  305.       case ZRINIT:
  306.          goto again;
  307.       case ZCAN:
  308.       case ZCRC:
  309.       case RCDO:
  310.       case TIMEOUT:
  311.       case ZABORT:
  312.       case ZFIN:
  313.          upderr(v, v->Msgbuf);
  314.          return ERROR;
  315.       case ZSKIP:             /* Receiver doesn't want this one */
  316.          upderr(v, "SKIP-Paket empfangen!");
  317.          bfclose(v);
  318.          return c;
  319.       case ZRPOS:             /* Receiver wants it; this is starting position */
  320.          bfseek(v, v->Rxpos);
  321.          v->Strtpos = v->Txpos = v->Rxpos;
  322.            xpr_sflush();
  323.          v->Modemcount = 0;
  324.          return zsendfdata(v);
  325.          }
  326.       }
  327.    }    /* End of short zsendfile() */
  328.  
  329. /**********************************************************
  330.  *    short zsendfdata(struct Vars *v)
  331.  *
  332.  * Send the file data
  333.  **********************************************************/
  334.  
  335. extern int zmodemmode;
  336.  
  337. static short zsendfdata(struct Vars *v)
  338. {
  339.    short c, e, blklen, goodbytes = 0;
  340.    USHORT framelen, maxblklen, goodneeded = 512;
  341.  
  342.    /* Figure out max data packet size to send */
  343.    maxblklen = KSIZE;
  344.    if (v->Rxbuflen && maxblklen > v->Rxbuflen)
  345.       maxblklen = v->Rxbuflen;
  346.    blklen = (v->Baud < 1200) ? 256 : KSIZE;
  347.    if (blklen > maxblklen)
  348.       blklen = maxblklen;
  349.  
  350.     if( !zmodemmode )
  351.     {
  352.         maxblklen = min( 1024, maxblklen );
  353.         blklen = min( 1024, blklen );
  354.     }
  355.  
  356. #ifdef DEBUGLOG
  357.    mysprintf(v->Msgbuf, "Rxbuflen=%ld blklen=%ld\n", (long) v->Rxbuflen,
  358.       (long) blklen);
  359.    dlog(v, v->Msgbuf);
  360. #endif
  361.  
  362.    /* If an interruption happened, handle it; else keep sending data */
  363. somemore:
  364.    while (char_avail(v))
  365.    {
  366.       /* Check for another incoming packet while discarding line noise */
  367.       switch (readock(v, 1))
  368.       {
  369.       case CAN:
  370.       case RCDO:
  371.       case ZPAD:
  372.          break;
  373.       default:
  374.          continue;
  375.          }
  376. waitack:
  377. #ifdef DEBUGLOG
  378.       dlog(v, "--- At waitack\n");
  379. #endif
  380.       switch (c = getinsync(v))
  381.       {
  382.       default:
  383.          upderr(v, "▄bertraung abgebrochen.");
  384.          bfclose(v);
  385.          return ERROR;
  386.       case ZSKIP:  /* Receiver changed its mind and wants to skip the file */
  387.          return c;
  388.       case ZACK:   /* ACK at end of frame; resume sending data */
  389.          break;
  390.       case ZRPOS:  /* An error; resend data from last good point */
  391.          blklen >>= 2;
  392.          if (blklen < MINBLOCK)
  393.         blklen = MINBLOCK;
  394.          if (goodneeded < MAXGOODNEEDED)
  395.         goodneeded <<= 1;
  396.          v->xpru.xpru_updatemask = XPRU_ERRORS;
  397.          ++v->xpru.xpru_errors;
  398.          xpr_update(&v->xpru);
  399.          break;
  400.       case ZRINIT:
  401.          updmsg(v, "▄bertragung erfolgreich beendet.");
  402.          return OK;
  403.          }
  404.       }
  405.  
  406.    /* Transmit ZDATA frame header */
  407.    framelen = v->Rxbuflen;
  408.    stohdr(v, v->Txpos);
  409.    zsbhdr(v, ZDATA);
  410.  
  411.    /* Keep sending data packets until finished or interrupted */
  412.    do
  413.    {
  414.       /* Read next chunk of file data */
  415.       c = bfread(v, v->Pktbuf, (long) blklen);
  416.  
  417.       /* Figure out how to handle this data packet */
  418.       if (c < blklen)
  419.          e = ZCRCE;  /* If end of file, this is last data packet */
  420.       else if (v->Rxbuflen && (framelen -= c) <= 0)
  421.          e = ZCRCW;  /* If end of frame, ask for ACK */
  422.       else
  423.          e = ZCRCG;  /* Else tell receiver to expect more data packets */
  424.  
  425.       zsdata(v, c, e);  /* Send the packet */
  426.       sendbuf(v);
  427.  
  428.       /* Update comm program status display */
  429.       v->xpru.xpru_updatemask = XPRU_BLOCKS | XPRU_BLOCKSIZE | XPRU_BYTES
  430.          | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE
  431.      | XPRU_BLOCKCHECK;
  432.       ++v->xpru.xpru_blocks;
  433.       v->xpru.xpru_blocksize = c;
  434.       v->xpru.xpru_blockcheck = v->Crc32t ? "CRC-32" : "CRC-16";
  435.       v->xpru.xpru_bytes = v->Txpos += c;
  436.       update_rate(v);
  437.       xpr_update(&v->xpru);
  438.  
  439.       /*
  440.        * If we've been sending smaller than normal packets, see if it's
  441.        * time to bump the packet size up a notch yet
  442.        */
  443.       if (blklen < maxblklen && (goodbytes += c) >= goodneeded)
  444.       {
  445.          blklen <<= 1;
  446.          if (blklen > maxblklen)
  447.         blklen = maxblklen;
  448.          goodbytes = 0;
  449. #ifdef DEBUGLOG
  450.          mysprintf(v->Msgbuf, "Bumping packet size to %ld at %ld\n",
  451.         (long) blklen, v->Txpos);
  452.          dlog(v, v->Msgbuf);
  453. #endif
  454.          }
  455.  
  456.       /* Give comm program its timeslice if it needs one */
  457.       /* Check for abort from comm program */
  458.       if (xpr_chkabort())
  459.      goto aborted;
  460.       /* If this was last packet in frame, go wait for ACK from receiver */
  461.       if (e == ZCRCW)
  462.      goto waitack;
  463.  
  464.       /*
  465.        * Check if receiver trying to interrupt us; look for incoming packet
  466.        * while discarding line noise
  467.        */
  468.       while (char_avail(v))
  469.       {
  470.          switch (readock(v, 1))
  471.      {
  472.          case CAN:
  473.          case RCDO:
  474.          case ZPAD:
  475.             /* Interruption detected; stop sending and process complaint */
  476. #ifdef DEBUGLOG
  477.             dlog(v, "--- Interrupted send\n");
  478. #endif
  479.             zsdata(v, 0, ZCRCE);
  480.             sendbuf(v);
  481.             goto waitack;
  482.             }
  483.          }
  484.       }
  485.    while (e == ZCRCG);  /* If no interruption, keep sending data packets */
  486.  
  487.    /* Done sending file data; send EOF and wait for receiver to acknowledge */
  488.    while (TRUE)
  489.    {
  490.       updmsg(v, "Sende EOF.");
  491.       stohdr(v, v->Txpos);
  492.       zsbhdr(v, ZEOF);
  493.       sendbuf(v);
  494.       switch (c = getinsync(v))
  495.       {
  496.       case ZACK:
  497.          continue;
  498.       case ZRPOS:
  499.          goto somemore;
  500.       case ZRINIT:
  501.          updmsg(v, "EOF bestΣtigt.");
  502.          ++v->Starttime.tv_secs;
  503.          update_rate(v);
  504.          v->xpru.xpru_updatemask = XPRU_EXPECTTIME | XPRU_ELAPSEDTIME
  505.         | XPRU_DATARATE;
  506.          xpr_update(&v->xpru);
  507.          return OK;
  508.       case ZSKIP:
  509.          return c;
  510.       default:
  511. aborted:
  512.      upderr(v, "▄bertragung abgebrochen!");
  513.          bfclose(v);
  514.          return ERROR;
  515.          }
  516.       }
  517.    }    /* End of short zsendfdata() */
  518.  
  519. /**********************************************************
  520.  *    short getinsync(struct Vars *v)
  521.  *
  522.  * Respond to receiver's complaint, get back in sync with
  523.  * receiver
  524.  **********************************************************/
  525. static short getinsync(struct Vars *v)
  526. {
  527.    short c;
  528.  
  529.    while (TRUE)
  530.    {
  531. #ifdef DEBUGLOG
  532.       dlog(v, "--- At getinsync\n");
  533. #endif
  534.       c = zgethdr(v);
  535.       xpr_sflush();
  536.       v->Modemcount = 0;
  537.       switch (c)
  538.       {
  539.       case ZCAN:
  540.       case ZABORT:
  541.       case ZFIN:
  542.       case RCDO:
  543.       case TIMEOUT:
  544.          upderr(v, v->Msgbuf);
  545.          return ERROR;
  546.       case ZRPOS:
  547.          bfseek(v, v->Rxpos);
  548.          v->Txpos = v->Rxpos;
  549.          mysprintf(v->Msgbuf, "Zurⁿck ab Offset %ld", v->Txpos);
  550.          upderr(v, v->Msgbuf);
  551.          return c;
  552.       case ZSKIP:
  553.          upderr(v, "SKIP-Paket empfangen!");
  554.          /* fallthrough... */
  555.       case ZRINIT:
  556.          bfclose(v);
  557.          /* fallthrough... */
  558.       case ZACK:
  559.          return c;
  560.       default:
  561.          zsbhdr(v, ZNAK);
  562.          sendbuf(v);
  563.          continue;
  564.          }
  565.       }
  566.    }    /* End of short getinsync() */
  567.  
  568. /**********************************************************
  569.  *    void saybibi(struct Vars *v)
  570.  *
  571.  * End of batch transmission; disengage cleanly from receiver
  572.  **********************************************************/
  573. static void saybibi(struct Vars *v)
  574. {
  575.    while (TRUE)
  576.    {
  577.       stohdr(v, 0L);
  578.       zsbhdr(v, ZFIN);
  579.       sendbuf(v);
  580.       switch (zgethdr(v))
  581.       {
  582.       case ZFIN:
  583.          sendline(v, 'O');
  584.          sendline(v, 'O');
  585.          sendbuf(v);
  586.          /* fallthrough... */
  587.       case ZCAN:
  588.       case RCDO:
  589.       case TIMEOUT:
  590.          return;
  591.          }
  592.       }
  593.    }    /* End of void saybibi() */
  594. /* End of Send.c source */
  595.