home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / BTMTSRC3.ZIP / ZRECEIVE.C < prev    next >
Text File  |  1991-12-21  |  31KB  |  1,147 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                            */
  3. /*                                                                            */
  4. /*        ------------         Bit-Bucket Software, Co.                        */
  5. /*        \ 10001101 /         Writers and Distributors of                    */
  6. /*         \ 011110 /          Freely Available<tm> Software.                 */
  7. /*          \ 1011 /                                                            */
  8. /*           ------                                                            */
  9. /*                                                                            */
  10. /*    (C) Copyright 1987-90, Bit Bucket Software Co., a Delaware Corporation. */
  11. /*                                                                            */
  12. /*                                                                            */
  13. /*                        Zmodem file reception module                        */
  14. /*                                                                            */
  15. /*                                                                            */
  16. /*      For complete    details  of the licensing restrictions, please refer    */
  17. /*      to the License  agreement,  which  is published in its entirety in    */
  18. /*      the MAKEFILE and BT.C, and also contained in the file LICENSE.240.    */
  19. /*                                                                            */
  20. /*      USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  21. /*      BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  22. /*      THIS    AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,    OR IF YOU DO    */
  23. /*      NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  24. /*      SOFTWARE CO.    AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  25. /*      SHOULD YOU  PROCEED TO USE THIS FILE    WITHOUT HAVING    ACCEPTED THE    */
  26. /*      TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  27. /*      AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.        */
  28. /*                                                                            */
  29. /*                                                                            */
  30. /* You can contact Bit Bucket Software Co. at any one of the following        */
  31. /* addresses:                                                                */
  32. /*                                                                            */
  33. /* Bit Bucket Software Co.          FidoNet  1:104/501, 1:132/491, 1:141/491    */
  34. /* P.O. Box 460398                  AlterNet 7:491/0                            */
  35. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  36. /*                                  Internet f491.n132.z1.fidonet.org         */
  37. /*                                                                            */
  38. /* Please feel free to contact us at any time to share your comments about    */
  39. /* our software and/or licensing policies.                                    */
  40. /*                                                                            */
  41. /*                                                                            */
  42. /*    This module is based largely on a similar module in OPUS-CBCS V1.03b.    */
  43. /*    The original work is (C) Copyright 1986, Wynn Wagner III. The original    */
  44. /*    authors have graciously allowed us to use their code in this work.        */
  45. /*                                                                            */
  46. /*--------------------------------------------------------------------------*/
  47.  
  48.  
  49. #include <sys\types.h>
  50. #include <sys\stat.h>
  51. #include <stdio.h>
  52. #include <fcntl.h>
  53. #include <ctype.h>
  54. #include <time.h>
  55. #include <string.h>
  56. #include <conio.h>
  57. #include <io.h>
  58. #include <stdlib.h>
  59.  
  60. #ifdef __TURBOC__
  61. #include "tc_utime.h"
  62. #else
  63. #include <sys/utime.h>
  64. #endif
  65.  
  66. #include "com.h"
  67. #include "xfer.h"
  68. #include "zmodem.h"
  69. #include "keybd.h"
  70. #include "sbuf.h"
  71. #include "sched.h"
  72. #include "externs.h"
  73. #include "prototyp.h"
  74.  
  75.  
  76.  
  77.  
  78. /*--------------------------------------------------------------------------*/
  79. /* Local routines                                                            */
  80. static int RZ_ReceiveData (byte *, int);
  81. static int RZ_32ReceiveData (byte *, int);
  82. static int RZ_InitReceiver (void);
  83. static int RZ_ReceiveBatch (FILE *);
  84. static int RZ_ReceiveFile (FILE *);
  85. static int RZ_GetHeader (void);
  86. static int RZ_SaveToDisk (unsigned long *);
  87. static void RZ_AckBibi (void);
  88.  
  89. /*--------------------------------------------------------------------------*/
  90. /* Private declarations                                                     */
  91. /*--------------------------------------------------------------------------*/
  92. static long DiskAvail;
  93. static long filetime;
  94. static byte realname[64];
  95.  
  96. /*--------------------------------------------------------------------------*/
  97. /* Private data                                                             */
  98. /*--------------------------------------------------------------------------*/
  99.  
  100. /* Parameters for ZSINIT frame */
  101. #define ZATTNLEN 32
  102.  
  103. static char Attn[ZATTNLEN + 1];                  /* String rx sends to tx on
  104.                                                   * err            */
  105. static FILE *Outfile;                             /* Handle of file being
  106.                                                   * received           */
  107. static int Tryzhdrtype;                          /* Hdr type to send for Last
  108.                                                   * rx close      */
  109. static char isBinary;                             /* Current file is binary
  110.                                                   * mode             */
  111. static char EOFseen;                             /* indicates cpm eof (^Z)
  112.                                                   * was received     */
  113. static char Zconv;                                 /* ZMODEM file conversion
  114.                                                   * request          */
  115. static int RxCount;                              /* Count of data bytes
  116.                                                   * received            */
  117. static byte Upload_path[PATHLEN];                 /* Dest. path of file being
  118.                                                   * received   */
  119. static long Filestart;                             /* File offset we started
  120.                                                   * this xfer from     */
  121. extern long filelength ();                         /* returns length of file
  122.                                                   * ref'd in stream  */
  123.  
  124. /*--------------------------------------------------------------------------*/
  125. /* GET ZMODEM                                                                */
  126. /* Receive a batch of files.                                                */
  127. /* returns TRUE (1) for good xfer, FALSE (0) for bad                        */
  128. /* can be called from f_upload or to get mail from a WaZOO Opus             */
  129. /*--------------------------------------------------------------------------*/
  130. int get_Zmodem (rcvpath, xferinfo)
  131. char *rcvpath;
  132. FILE *xferinfo;
  133. {
  134.    byte namebuf[PATHLEN];
  135.    int i;
  136.    byte *p;
  137.    char *HoldName;
  138.    long t;
  139.  
  140. #ifdef DEBUG
  141.    show_debug_name ("get_Zmodem");
  142. #endif
  143.  
  144.    filetime = 0;
  145.  
  146.    _BRK_DISABLE ();
  147.    IN_XON_ENABLE ();
  148.  
  149. /*     Secbuf = NULL;*/
  150.    Outfile = NULL;
  151.    z_size = 0;
  152.  
  153.  
  154.    Rxtimeout = 100;
  155.    Tryzhdrtype = ZRINIT;
  156.  
  157.    strcpy (namebuf, rcvpath);
  158.    Filename = namebuf;
  159.  
  160.    strcpy (Upload_path, rcvpath);
  161.    p = Upload_path + strlen (Upload_path) - 1;
  162.    while (p >= Upload_path && *p != '\\')
  163.       --p;
  164.    *(++p) = '\0';
  165.  
  166.    HoldName = HoldAreaNameMunge(&called_addr);
  167.  
  168.    sprintf (Abortlog_name, "%s%s.Z\0",
  169.             HoldName, Hex_Addr_Str (&remote_addr));
  170.  
  171.    DiskAvail = zfree (Upload_path);
  172.  
  173.    if (((i = RZ_InitReceiver ()) == ZCOMPL) ||
  174.        ((i == ZFILE) && ((RZ_ReceiveBatch (xferinfo)) == OK)))
  175.       {
  176.       XON_DISABLE ();
  177.       XON_ENABLE ();                             /* Make sure xmitter is
  178.                                                   * unstuck */
  179.       return 1;
  180.       }
  181.  
  182.    CLEAR_OUTBOUND ();
  183.    XON_DISABLE ();                                 /* Make sure xmitter is
  184.                                                   * unstuck */
  185.    send_can ();                                  /* transmit at least 10 cans     */
  186.    t = timerset (200);                             /* wait no more than 2
  187.                                                   * seconds  */
  188.    while (!timeup (t) && !OUT_EMPTY () && CARRIER)
  189.       time_release ();                             /* Give up slice while
  190.                                                   * waiting  */
  191.    XON_ENABLE ();                                 /* Turn XON/XOFF back on...     */
  192. /*
  193.    if (Secbuf)
  194.       free (Secbuf);
  195. */
  196.    if (Outfile)
  197.       fclose (Outfile);
  198.  
  199.    return 0;
  200. }                                                 /* get_Zmodem */
  201.  
  202. /*--------------------------------------------------------------------------*/
  203. /* RZ RECEIVE DATA                                                            */
  204. /* Receive array buf of max length with ending ZDLE sequence                */
  205. /* and CRC.  Returns the ending character or error code.                    */
  206. /*--------------------------------------------------------------------------*/
  207. static int RZ_ReceiveData (buf, length)
  208. register byte *buf;
  209. register int length;
  210. {
  211.    register int c;
  212.    register word crc;
  213.    char *endpos;
  214.    int d;
  215.  
  216.  
  217. #ifdef DEBUG
  218.    show_debug_name ("RZ_ReceiveData");
  219. #endif
  220.  
  221.    if (Rxframeind == ZBIN32)
  222.       return RZ_32ReceiveData (buf, length);
  223.  
  224.    crc = RxCount = 0;
  225.    buf[0] = buf[1] = 0;
  226.    endpos = buf + length;
  227.  
  228.    while (buf <= endpos)
  229.       {
  230.       if ((c = Z_GetZDL ()) & ~0xFF)
  231.          {
  232.    CRCfoo:
  233.          switch (c)
  234.             {
  235.             case GOTCRCE:
  236.             case GOTCRCG:
  237.             case GOTCRCQ:
  238.             case GOTCRCW:
  239.                /*-----------------------------------*/
  240.                /* C R C s                            */
  241.                /*-----------------------------------*/
  242.                crc = Z_UpdateCRC (((d = c) & 0xFF), crc);
  243.                if ((c = Z_GetZDL ()) & ~0xFF)
  244.                   goto CRCfoo;
  245.  
  246.                crc = Z_UpdateCRC (c, crc);
  247.                if ((c = Z_GetZDL ()) & ~0xFF)
  248.                   goto CRCfoo;
  249.  
  250.                crc = Z_UpdateCRC (c, crc);
  251.                if (crc & 0xFFFF)
  252.                   {
  253.                   z_message (msgtxt[M_CRC_MSG]);
  254.                   return ERROR;
  255.                   }
  256.  
  257.                RxCount = length - (endpos - buf);
  258.                return d;
  259.  
  260.             case GOTCAN:
  261.                /*-----------------------------------*/
  262.                /* Cancel                            */
  263.                /*-----------------------------------*/
  264.                z_log (msgtxt[M_CAN_MSG]);
  265.                return ZCAN;
  266.  
  267.             case TIMEOUT:
  268.                /*-----------------------------------*/
  269.                /* Timeout                            */
  270.                /*-----------------------------------*/
  271.                z_message (msgtxt[M_TIMEOUT]);
  272.                return c;
  273.  
  274.             case RCDO:
  275.                /*-----------------------------------*/
  276.                /* No carrier                        */
  277.                /*-----------------------------------*/
  278.                z_log (msgtxt[M_NO_CARRIER]);
  279.                CLEAR_INBOUND ();
  280.                return c;
  281.  
  282.             default:
  283.                /*-----------------------------------*/
  284.                /* Something bizarre                 */
  285.                /*-----------------------------------*/
  286.                z_message (msgtxt[M_DEBRIS]);
  287.                CLEAR_INBOUND ();
  288.                return c;
  289.             }                                     /* switch */
  290.          }                                         /* if */
  291.  
  292.       *buf++ = (unsigned char) c;
  293.       crc = Z_UpdateCRC (c, crc);
  294.       }                                          /* while(1) */
  295.  
  296.    z_message (msgtxt[M_LONG_PACKET]);
  297.    return ERROR;
  298. }                                                 /* RZ_ReceiveData */
  299.  
  300. /*--------------------------------------------------------------------------*/
  301. /* RZ RECEIVE DATA with 32 bit CRC                                            */
  302. /* Receive array buf of max length with ending ZDLE sequence                */
  303. /* and CRC.  Returns the ending character or error code.                    */
  304. /*--------------------------------------------------------------------------*/
  305. static int RZ_32ReceiveData (buf, length)
  306. register byte *buf;
  307. register int length;
  308. {
  309.    register int c;
  310.    unsigned long crc;
  311.    char *endpos;
  312.    int d;
  313.  
  314.  
  315. #ifdef DEBUG
  316.    show_debug_name ("RZ_32ReceiveData");
  317. #endif
  318.  
  319.    crc = 0xFFFFFFFF;
  320.    RxCount = 0;
  321.    buf[0] = buf[1] = 0;
  322.    endpos = buf + length;
  323.  
  324.    while (buf <= endpos)
  325.       {
  326.       if ((c = Z_GetZDL ()) & ~0xFF)
  327.          {
  328.    CRCfoo:
  329.          switch (c)
  330.             {
  331.             case GOTCRCE:
  332.             case GOTCRCG:
  333.             case GOTCRCQ:
  334.             case GOTCRCW:
  335.                /*-----------------------------------*/
  336.                /* C R C s                            */
  337.                /*-----------------------------------*/
  338.                d = c;
  339.                c &= 0377;
  340.                crc = Z_32UpdateCRC (c, crc);
  341.                if ((c = Z_GetZDL ()) & ~0xFF)
  342.                   goto CRCfoo;
  343.  
  344.                crc = Z_32UpdateCRC (c, crc);
  345.                if ((c = Z_GetZDL ()) & ~0xFF)
  346.                   goto CRCfoo;
  347.  
  348.                crc = Z_32UpdateCRC (c, crc);
  349.                if ((c = Z_GetZDL ()) & ~0xFF)
  350.                   goto CRCfoo;
  351.  
  352.                crc = Z_32UpdateCRC (c, crc);
  353.                if ((c = Z_GetZDL ()) & ~0xFF)
  354.                   goto CRCfoo;
  355.  
  356.                crc = Z_32UpdateCRC (c, crc);
  357.                if (crc != 0xDEBB20E3)
  358.                   {
  359.                   z_message (msgtxt[M_CRC_MSG]);
  360.                   return ERROR;
  361.                   }
  362.  
  363.                RxCount = length - (endpos - buf);
  364.                return d;
  365.  
  366.             case GOTCAN:
  367.                /*-----------------------------------*/
  368.                /* Cancel                            */
  369.                /*-----------------------------------*/
  370.                z_log (msgtxt[M_CAN_MSG]);
  371.                return ZCAN;
  372.  
  373.             case TIMEOUT:
  374.                /*-----------------------------------*/
  375.                /* Timeout                            */
  376.                /*-----------------------------------*/
  377.                z_message (msgtxt[M_TIMEOUT]);
  378.                return c;
  379.  
  380.             case RCDO:
  381.                /*-----------------------------------*/
  382.                /* No carrier                        */
  383.                /*-----------------------------------*/
  384.                z_log (msgtxt[M_NO_CARRIER]);
  385.                CLEAR_INBOUND ();
  386.                return c;
  387.  
  388.             default:
  389.                /*-----------------------------------*/
  390.                /* Something bizarre                 */
  391.                /*-----------------------------------*/
  392.                z_message (msgtxt[M_DEBRIS]);
  393.                CLEAR_INBOUND ();
  394.                return c;
  395.             }                                     /* switch */
  396.          }                                         /* if */
  397.  
  398.       *buf++ = (unsigned char) c;
  399.       crc = Z_32UpdateCRC (c, crc);
  400.       }                                          /* while(1) */
  401.  
  402.    z_message (msgtxt[M_LONG_PACKET]);
  403.    return ERROR;
  404. }                                                 /* RZ_ReceiveData */
  405.  
  406. /*--------------------------------------------------------------------------*/
  407. /* RZ INIT RECEIVER                                                         */
  408. /* Initialize for Zmodem receive attempt, try to activate Zmodem sender     */
  409. /* Handles ZSINIT, ZFREECNT, and ZCOMMAND frames                            */
  410. /*                                                                            */
  411. /* Return codes:                                                            */
  412. /*      ZFILE .... Zmodem filename received                                    */
  413. /*      ZCOMPL ... transaction finished                                        */
  414. /*      ERROR .... any other condition                                        */
  415. /*--------------------------------------------------------------------------*/
  416. static int RZ_InitReceiver ()
  417. {
  418.    register int n;
  419.    int errors = 0;
  420.    char *sptr;
  421.  
  422.  
  423. #ifdef DEBUG
  424.    show_debug_name ("RZ_InitReceiver");
  425. #endif
  426.  
  427.    for (n = 12; --n >= 0;)
  428.       {
  429.       /*--------------------------------------------------------------*/
  430.       /* Set buffer length (0=unlimited, don't wait).                 */
  431.       /* Also set capability flags                                      */
  432.       /*--------------------------------------------------------------*/
  433.       Z_PutLongIntoHeader (0L);
  434.       Txhdr[ZF0] = CANFC32 | CANFDX | CANOVIO;
  435.       Z_SendHexHeader (Tryzhdrtype, Txhdr);
  436.       if (Tryzhdrtype == ZSKIP)
  437.          Tryzhdrtype = ZRINIT;
  438.  
  439. AGAIN:
  440.  
  441.       switch (Z_GetHeader (Rxhdr))
  442.          {
  443.          case ZFILE:
  444.             Zconv = Rxhdr[ZF0];
  445.             Tryzhdrtype = ZRINIT;
  446.             if (RZ_ReceiveData (Secbuf, WAZOOMAX) == GOTCRCW)
  447.                return ZFILE;
  448.             Z_SendHexHeader (ZNAK, Txhdr);
  449.             if (--n < 0)
  450.                {
  451.                sptr = "ZFILE";
  452.                goto Err;
  453.                }
  454.             goto AGAIN;
  455.  
  456.          case ZSINIT:
  457.             if (RZ_ReceiveData (Attn, ZATTNLEN) == GOTCRCW)
  458.                {
  459.                Z_PutLongIntoHeader (1L);
  460.                Z_SendHexHeader (ZACK, Txhdr);
  461.                }
  462.             else Z_SendHexHeader (ZNAK, Txhdr);
  463.             if (--n < 0)
  464.                {
  465.                sptr = "ZSINIT";
  466.                goto Err;
  467.                }
  468.             goto AGAIN;
  469.  
  470.          case ZFREECNT:
  471.             Z_PutLongIntoHeader (DiskAvail);
  472.             Z_SendHexHeader (ZACK, Txhdr);
  473.             goto AGAIN;
  474.  
  475.          case ZCOMMAND:
  476.             /*-----------------------------------------*/
  477.             /* Paranoia is good for you...               */
  478.             /* Ignore command from remote, but lie and */
  479.             /* say we did the command ok.               */
  480.             /*-----------------------------------------*/
  481.             if (RZ_ReceiveData (Secbuf, WAZOOMAX) == GOTCRCW)
  482.                {
  483.                status_line (msgtxt[M_Z_IGNORING], Secbuf);
  484.                Z_PutLongIntoHeader (0L);
  485.                do
  486.                   {
  487.                   Z_SendHexHeader (ZCOMPL, Txhdr);
  488.                   }
  489.                while (++errors < 10 && Z_GetHeader (Rxhdr) != ZFIN);
  490.                RZ_AckBibi ();
  491.                return ZCOMPL;
  492.                }
  493.             else Z_SendHexHeader (ZNAK, Txhdr);
  494.             if (--n < 0)
  495.                {
  496.                sptr = "CMD";
  497.                goto Err;
  498.                }
  499.             goto AGAIN;
  500.  
  501.          case ZCOMPL:
  502.             if (--n < 0)
  503.                {
  504.                sptr = "COMPL";
  505.                goto Err;
  506.                }
  507.             goto AGAIN;
  508.  
  509.          case ZFIN:
  510.             RZ_AckBibi ();
  511.             return ZCOMPL;
  512.  
  513.          case ZCAN:
  514.             sptr = msgtxt[M_CAN_MSG];
  515.             goto Err;
  516.  
  517.          case RCDO:
  518.             sptr = &(msgtxt[M_NO_CARRIER][1]);
  519.             CLEAR_INBOUND ();
  520.             goto Err;
  521.          }                                         /* switch */
  522.       }                                          /* for */
  523.  
  524.    sptr = msgtxt[M_TIMEOUT];
  525.  
  526. Err:
  527.    sprintf (e_input, msgtxt[M_Z_INITRECV], sptr);
  528.    z_log (e_input);
  529.  
  530.    return ERROR;
  531. }                                                 /* RZ_InitReceiver */
  532.  
  533. /*--------------------------------------------------------------------------*/
  534. /* RZFILES                                                                    */
  535. /* Receive a batch of files using ZMODEM protocol                            */
  536. /*--------------------------------------------------------------------------*/
  537. static int RZ_ReceiveBatch (xferinfo)
  538. FILE *xferinfo;
  539. {
  540.    register int c;
  541.    byte namebuf[PATHLEN];
  542.  
  543.  
  544. #ifdef DEBUG
  545.    show_debug_name ("RZ_ReceiveBatch");
  546. #endif
  547.  
  548.    while (1)
  549.       {
  550.       switch (c = RZ_ReceiveFile (xferinfo))
  551.          {
  552.          case ZEOF:
  553.             if (Resume_WaZOO)
  554.                {
  555.                     remove_abort (Abortlog_name, Resume_name);
  556.                strcpy (namebuf, Upload_path);
  557.                strcat (namebuf, Resume_name);
  558.                unique_name (namebuf);
  559.                rename (Filename, namebuf);
  560.                }
  561.             /* fallthrough */
  562.          case ZSKIP:
  563.             switch (RZ_InitReceiver ())
  564.                {
  565.                case ZCOMPL:
  566.                   return OK;
  567.                default:
  568.                   return ERROR;
  569.                case ZFILE:
  570.                   break;
  571.                }                                 /* switch */
  572.             break;
  573.  
  574.          default:
  575.             fclose (Outfile);
  576.             Outfile = NULL;
  577.             if (remote_capabilities)
  578.                {
  579.                if (!Resume_WaZOO)
  580.                   {
  581.                         add_abort (Abortlog_name, Resume_name, Filename, Upload_path, Resume_info);
  582.                   }
  583.                }
  584.             else unlink (Filename);
  585.             return c;
  586.          }                                         /* switch */
  587.       }                                          /* while */
  588. }                                                 /* RZ_ReceiveBatch */
  589.  
  590. /*--------------------------------------------------------------------------*/
  591. /* RZ RECEIVE FILE                                                            */
  592. /* Receive one file; assumes file name frame is preloaded in Secbuf         */
  593. /*--------------------------------------------------------------------------*/
  594. static int RZ_ReceiveFile (xferinfo)
  595. FILE *xferinfo;
  596. {
  597.    register int c;
  598.    int n;
  599.    long rxbytes;
  600.    char *sptr;
  601.    struct utimbuf utimes;
  602.    char j[50];
  603.  
  604.  
  605. #ifdef DEBUG
  606.    show_debug_name ("RZ_ReceiveFile");
  607. #endif
  608.  
  609.    EOFseen = FALSE;
  610.    c = RZ_GetHeader ();
  611.    if (c == ERROR || c == ZSKIP)
  612.       return (Tryzhdrtype = ZSKIP);
  613.  
  614.    n = 10;
  615.    rxbytes = Filestart;
  616.  
  617.    while (1)
  618.       {
  619.       Z_PutLongIntoHeader (rxbytes);
  620.       Z_SendHexHeader (ZRPOS, Txhdr);
  621. NxtHdr:
  622.       switch (c = Z_GetHeader (Rxhdr))
  623.          {
  624.          case ZDATA:
  625.             /*-----------------------------------------*/
  626.             /* Data Packet                               */
  627.             /*-----------------------------------------*/
  628.             if (Rxpos != rxbytes)
  629.                {
  630.                if (--n < 0)
  631.                   {
  632.                   sptr = msgtxt[M_FUBAR_MSG];
  633.                   goto Err;
  634.                   }
  635.                sprintf (j, "%s; %ld/%ld", msgtxt[M_BAD_POS], rxbytes, Rxpos);
  636.                z_message (j);
  637.                Z_PutString (Attn);
  638.                continue;
  639.                }
  640.       MoreData:
  641.             switch (c = RZ_ReceiveData (Secbuf, WAZOOMAX))
  642.                {
  643.                case ZCAN:
  644.                   sptr = msgtxt[M_CAN_MSG];
  645.                   goto Err;
  646.  
  647.                case RCDO:
  648.                   sptr = &(msgtxt[M_NO_CARRIER][1]);
  649.                   CLEAR_INBOUND ();
  650.                   goto Err;
  651.  
  652.                case ERROR:
  653.                   /*-----------------------*/
  654.                   /* CRC error               */
  655.                   /*-----------------------*/
  656.                   if (--n < 0)
  657.                      {
  658.                      sptr = msgtxt[M_FUBAR_MSG];
  659.                      goto Err;
  660.                      }
  661.                   show_loc (rxbytes, n);
  662.                   Z_PutString (Attn);
  663.                   continue;
  664.  
  665.                case TIMEOUT:
  666.                   if (--n < 0)
  667.                      {
  668.                      sptr = msgtxt[M_TIMEOUT];
  669.                      goto Err;
  670.                      }
  671.                   show_loc (rxbytes, n);
  672.                   continue;
  673.  
  674.                case GOTCRCW:
  675.                   /*---------------------*/
  676.                   /* End of frame           */
  677.                   /*-----------------------*/
  678.                   n = 10;
  679.                   if (RZ_SaveToDisk (&rxbytes) == ERROR)
  680.                      return ERROR;
  681.                   Z_PutLongIntoHeader (rxbytes);
  682.                   Z_SendHexHeader (ZACK, Txhdr);
  683.                   goto NxtHdr;
  684.  
  685.                case GOTCRCQ:
  686.                   /*---------------------*/
  687.                   /* Zack expected           */
  688.                   /*-----------------------*/
  689.                   n = 10;
  690.                   if (RZ_SaveToDisk (&rxbytes) == ERROR)
  691.                      return ERROR;
  692.                   Z_PutLongIntoHeader (rxbytes);
  693.                   Z_SendHexHeader (ZACK, Txhdr);
  694.                   goto MoreData;
  695.  
  696.                case GOTCRCG:
  697.                   /*---------------------*/
  698.                   /* Non-stop               */
  699.                   /*-----------------------*/
  700.                   n = 10;
  701.                   if (RZ_SaveToDisk (&rxbytes) == ERROR)
  702.                      return ERROR;
  703.                   goto MoreData;
  704.  
  705.                case GOTCRCE:
  706.                   /*---------------------*/
  707.                   /* Header to follow       */
  708.                   /*-----------------------*/
  709.                   n = 10;
  710.                   if (RZ_SaveToDisk (&rxbytes) == ERROR)
  711.                      return ERROR;
  712.                   goto NxtHdr;
  713.                }                                 /* switch */
  714.  
  715.          case ZNAK:
  716.          case TIMEOUT:
  717.             /*-----------------------------------------*/
  718.             /* Packet was probably garbled               */
  719.             /*-----------------------------------------*/
  720.             if (--n < 0)
  721.                {
  722.                sptr = msgtxt[M_JUNK_BLOCK];
  723.                goto Err;
  724.                }
  725.             show_loc (rxbytes, n);
  726.             continue;
  727.  
  728.          case ZFILE:
  729.             /*-----------------------------------------*/
  730.             /* Sender didn't see our ZRPOS yet         */
  731.             /*-----------------------------------------*/
  732.             RZ_ReceiveData (Secbuf, WAZOOMAX);
  733.             continue;
  734.  
  735.          case ZEOF:
  736.             /*-----------------------------------------*/
  737.             /* End of the file                           */
  738.             /* Ignore EOF if it's at wrong place; force */
  739.             /* a timeout because the eof might have    */
  740.             /* gone out before we sent our ZRPOS       */
  741.             /*-----------------------------------------*/
  742.             if (locate_y && !(fullscreen && un_attended))
  743.                gotoxy (2, (byte) locate_y - 1);
  744.             if (Rxpos != rxbytes)
  745.                goto NxtHdr;
  746.  
  747.             throughput (2, rxbytes - Filestart);
  748.  
  749.             fclose (Outfile);
  750.  
  751.             status_line ("%s-Z%s %s", msgtxt[M_FILE_RECEIVED], Crc32 ? "/32" : "", realname);
  752.  
  753.             update_files (0);
  754.  
  755.             if (filetime)
  756.                {
  757.                utimes.actime = filetime;
  758.                utimes.modtime = filetime;
  759.                utime (Filename, &utimes);
  760.                }
  761.  
  762.             Outfile = NULL;
  763.             if (xferinfo != NULL)
  764.                {
  765.                fprintf (xferinfo, "%s\n", Filename);
  766.                }
  767.             return c;
  768.  
  769.          case ERROR:
  770.             /*-----------------------------------------*/
  771.             /* Too much garbage in header search error */
  772.             /*-----------------------------------------*/
  773.             if (--n < 0)
  774.                {
  775.                sptr = msgtxt[M_JUNK_BLOCK];
  776.                goto Err;
  777.                }
  778.             show_loc (rxbytes, n);
  779.             Z_PutString (Attn);
  780.             continue;
  781.  
  782.          case ZSKIP:
  783.             return c;
  784.  
  785.          default:
  786.             sptr = IDUNNO_msg;
  787.             CLEAR_INBOUND ();
  788.             goto Err;
  789.          }                                         /* switch */
  790.       }                                          /* while */
  791.  
  792. Err:sprintf (e_input, msgtxt[M_Z_RZ], sptr);
  793.    z_log (e_input);
  794.    return ERROR;
  795. }                                                 /* RZ_ReceiveFile */
  796.  
  797. /*--------------------------------------------------------------------------*/
  798. /* RZ GET HEADER                                                            */
  799. /* Process incoming file information header                                 */
  800. /*--------------------------------------------------------------------------*/
  801. static int RZ_GetHeader ()
  802. {
  803.    register byte *p;
  804.    struct stat f;
  805.    int i;
  806.    byte *ourname;
  807.    byte *theirname;
  808.    unsigned long filesize;
  809.    byte *fileinfo;
  810.    char j[80];
  811.     char fullname[20];
  812.     char fname[9];
  813.     char ext[4];
  814.     char *cptr;
  815.     char *cptr1;
  816.  
  817.  
  818. #ifdef DEBUG
  819.    show_debug_name ("RZ_GetHeader");
  820. #endif
  821.  
  822.    /*--------------------------------------------------------------------*/
  823.    /* Setup the transfer mode                                             */
  824.    /*--------------------------------------------------------------------*/
  825.    isBinary = (char) ((!RXBINARY && Zconv == ZCNL) ? 0 : 1);
  826.    Resume_WaZOO = 0;
  827.  
  828.    /*--------------------------------------------------------------------*/
  829.    /* Extract and verify filesize, if given.                             */
  830.    /* Reject file if not at least 10K free                                 */
  831.    /*--------------------------------------------------------------------*/
  832.    filesize = 0L;
  833.    filetime = 0L;
  834.    fileinfo = Secbuf + 1 + strlen (Secbuf);
  835.    if (*fileinfo)
  836.       sscanf (fileinfo, "%ld %lo", &filesize, &filetime);
  837.    if (filesize + 10240 > DiskAvail)
  838.       {
  839.       status_line (msgtxt[M_OUT_OF_DISK_SPACE]);
  840.       return ERROR;
  841.       }
  842.  
  843.    /*--------------------------------------------------------------------*/
  844.    /* Get and/or fix filename for uploaded file                          */
  845.    /*--------------------------------------------------------------------*/
  846.    p = Filename + strlen (Filename) - 1;         /* Find end of upload path */
  847.    while (p >= Filename && *p != '\\')
  848.       p--;
  849.    ourname = ++p;
  850.  
  851.    p = Secbuf + strlen (Secbuf) - 1;             /* Find transmitted simple
  852.                                                   * filename */
  853.    while (p >= Secbuf && *p != '\\' && *p != '/' && *p != ':')
  854.       p--;
  855.    theirname = ++p;
  856.  
  857.     /*----------------*/
  858.     cptr = fname;
  859.     cptr1 = theirname;
  860.     while (*cptr1 && *cptr1 != '.' && cptr < (fname + 8))        /* CML - cut to 8.3 for now */
  861.         *cptr++ = *cptr1++;
  862.     *cptr = '\0';
  863.  
  864.     while (*cptr1 && *cptr1 != '.')
  865.         ++cptr1;
  866.     if (*cptr1 == '.')
  867.         ++cptr1;
  868.  
  869.     cptr = ext;
  870.     while (*cptr1 && *cptr1 != '.' && cptr < (ext + 3))
  871.         *cptr++ = *cptr1++;
  872.     *cptr = '\0';
  873.  
  874.     sprintf(fullname,"%s%s%s",fname,(char *)(ext[0] ? "." : ""),ext);
  875.     theirname = fullname;
  876.     /*----------------*/
  877.  
  878.  
  879.    strcpy (ourname, theirname);                  /* Start w/ our path & their
  880.                                                   * name */
  881.    strcpy (realname, Filename);
  882.  
  883.    /*--------------------------------------------------------------------*/
  884.    /* Save info on WaZOO transfer in case of abort                         */
  885.    /*--------------------------------------------------------------------*/
  886.    if (remote_capabilities)
  887.       {
  888.       strcpy (Resume_name, theirname);
  889.       sprintf (Resume_info, "%ld %lo", filesize, filetime);
  890.       }
  891.  
  892.    /*--------------------------------------------------------------------*/
  893.    /* Check if this is a failed WaZOO transfer which should be resumed     */
  894.    /*--------------------------------------------------------------------*/
  895.    if (remote_capabilities && dexists (Abortlog_name))
  896.       {
  897.         Resume_WaZOO = (byte) check_failed (Abortlog_name, theirname, Resume_info, ourname);
  898.       }
  899.  
  900.    /*--------------------------------------------------------------------*/
  901.    /* Open either the old or a new file, as appropriate                  */
  902.    /*--------------------------------------------------------------------*/
  903.    if (Resume_WaZOO)
  904.       {
  905.       if (dexists (Filename))
  906.          p = "r+b";
  907.       else p = write_binary;
  908.       }
  909.    else
  910.       {
  911.       strcpy (ourname, theirname);
  912.       /*--------------------------------------------------------------------*/
  913.       /* If the file already exists:                                        */
  914.       /* 1) And the new file has the same time and size, return ZSKIP     */
  915.       /* 2) And OVERWRITE is turned on, delete the old copy              */
  916.       /* 3) Else create a unique file name in which to store new data     */
  917.       /*--------------------------------------------------------------------*/
  918.       if (dexists (Filename))
  919.          {                                         /* If file already exists...       */
  920.          if ((Outfile = fopen (Filename, read_binary)) == NULL)
  921.             {
  922.             (void) got_error (msgtxt[M_OPEN_MSG], Filename);
  923.             return ERROR;
  924.             }
  925.          fstat (fileno (Outfile), &f);
  926.          fclose (Outfile);
  927.          if (filesize == f.st_size && filetime == f.st_mtime)
  928.             {
  929.             status_line (msgtxt[M_ALREADY_HAVE], Filename);
  930.             return ZSKIP;
  931.             }
  932.          i = strlen (Filename) - 1;
  933.          if ((!overwrite) || (is_arcmail (Filename, i)))
  934.             {
  935.             unique_name (Filename);
  936.             }
  937.          else
  938.             {
  939.             unlink (Filename);
  940.             }
  941.          }                                         /* if exist */
  942.  
  943.       if (strcmp (ourname, theirname))
  944.          {
  945.          status_line (msgtxt[M_RENAME_MSG], ourname);
  946.          }
  947.       p = write_binary;
  948.       }
  949.    if ((Outfile = fopen (Filename, p)) == NULL)
  950.       {
  951.       (void) got_error (msgtxt[M_OPEN_MSG], Filename);
  952.       return ERROR;
  953.       }
  954.    if (isatty (fileno (Outfile)))
  955.       {
  956.       errno = 1;
  957.       (void) got_error (msgtxt[M_DEVICE_MSG], Filename);
  958.       fclose (Outfile);
  959.       return (ERROR);
  960.       }
  961.  
  962.    Filestart = (Resume_WaZOO) ? filelength (fileno (Outfile)) : 0L;
  963.    if (Resume_WaZOO)
  964.       status_line (msgtxt[M_SYNCHRONIZING_OFFSET], Filestart);
  965.    fseek (Outfile, Filestart, SEEK_SET);
  966.  
  967.    if (remote_capabilities)
  968.         p = check_netfile(theirname);
  969.    else p = NULL;
  970.  
  971.     if (lock_baud)                /* CML calculate correct time */
  972.         sprintf (j, "%s %s; %s%ldb, %d min.",(p) ? p : msgtxt[M_RECEIVING],realname,(isBinary) ? "" : "ASCII ",filesize,(int) ((filesize - Filestart) * 10 / actual_baud + 53) / 54);
  973.     else 
  974.         sprintf (j, "%s %s; %s%ldb, %d min.",(p) ? p : msgtxt[M_RECEIVING],realname,(isBinary) ? "" : "ASCII ",filesize,(int) ((filesize - Filestart) * 10 / cur_baud + 53) / 54);
  975.  
  976.    file_length = filesize;
  977.  
  978.    if (un_attended && fullscreen)
  979.       {
  980.       clear_filetransfer ();
  981.       sb_move (filewin, 1, 2);
  982.       sb_puts (filewin, j);
  983.       elapse_time ();
  984.         if (lock_baud)                /* CML calculate correct time */
  985.             i = (int) (filesize * 10 / actual_baud + 53) / 54;
  986.         else 
  987.             i = (int) (filesize * 10 / cur_baud + 53) / 54;
  988.       sb_move (filewin, 2, 69);
  989.       sprintf(j, "%3d min", i);
  990.       sb_puts (filewin, j);
  991.       sb_show ();
  992.       }
  993.    else
  994.       {
  995.       set_xy (j);
  996.       set_xy (NULL);
  997.       locate_x += 2;
  998.       }
  999.  
  1000.    throughput (0, 0L);
  1001.  
  1002.    return OK;
  1003. }                                                 /* RZ_GetHeader */
  1004.  
  1005. /*--------------------------------------------------------------------------*/
  1006. /* RZ SAVE TO DISK                                                            */
  1007. /* Writes the received file data to the output file.                        */
  1008. /* If in ASCII mode, stops writing at first ^Z, and converts all            */
  1009. /*     solo CR's or LF's to CR/LF pairs.                                      */
  1010. /*--------------------------------------------------------------------------*/
  1011. static int RZ_SaveToDisk (rxbytes)
  1012. unsigned long *rxbytes;
  1013. {
  1014.    static byte lastsent;
  1015.  
  1016.    register byte *p;
  1017.    register int count;
  1018.    int i;
  1019.    char j[100];
  1020.  
  1021. #ifdef DEBUG
  1022.    show_debug_name ("RZ_SaveToDisk");
  1023. #endif
  1024.  
  1025.    count = RxCount;
  1026.  
  1027.    if (got_ESC ())
  1028.       {
  1029.       send_can ();                                 /* Cancel file */
  1030.       while ((i = Z_GetByte (20)) != TIMEOUT && i != RCDO)        /* Wait for line to
  1031.                                                                  * clear */
  1032.          CLEAR_INBOUND ();
  1033.       send_can ();                                 /* and Cancel Batch */
  1034.       z_log (msgtxt[M_KBD_MSG]);
  1035.       return ERROR;
  1036.       }
  1037.  
  1038.    if (count != z_size)
  1039.       {
  1040.       if (fullscreen && un_attended)
  1041.          {
  1042.          sb_move (filewin, 2, 12);
  1043.          sb_puts (filewin, ultoa (((unsigned long) (z_size = count)), e_input, 10));
  1044.          sb_puts (filewin, "    ");
  1045.          elapse_time ();
  1046.          sb_show ();
  1047.          }
  1048.       else
  1049.          {
  1050.          gotoxy (locate_x + 10, locate_y);
  1051.          cputs (ultoa (((unsigned long) (z_size = count)), e_input, 10));
  1052.          putch (' ');
  1053.          }
  1054.       }
  1055.  
  1056.    if (isBinary)
  1057.       {
  1058.       if (fwrite (Secbuf, 1, count, Outfile) != count)
  1059.          goto oops;
  1060.       }
  1061.    else
  1062.       {
  1063.       if (EOFseen)
  1064.          return OK;
  1065.       for (p = Secbuf; --count >= 0; ++p)
  1066.          {
  1067.          if (*p == CPMEOF)
  1068.             {
  1069.             EOFseen = TRUE;
  1070.             return OK;
  1071.             }
  1072.          if (*p == '\n')
  1073.             {
  1074.             if (lastsent != '\r' && putc ('\r', Outfile) == EOF)
  1075.                goto oops;
  1076.             }
  1077.          else
  1078.             {
  1079.             if (lastsent == '\r' && putc ('\n', Outfile) == EOF)
  1080.                goto oops;
  1081.             }
  1082.          if (putc ((lastsent = *p), Outfile) == EOF)
  1083.             goto oops;
  1084.          }
  1085.       }
  1086.  
  1087.    *rxbytes += RxCount;
  1088.    i = (int) ((file_length - *rxbytes)* 10 / cur_baud + 53) / 54;
  1089.    sprintf (j, "%3d min", i);
  1090.  
  1091.  
  1092.    if (fullscreen && un_attended)
  1093.       {
  1094.       elapse_time();
  1095.       sb_move (filewin, 2, 2);
  1096.       sb_puts (filewin, ultoa (((unsigned long) (*rxbytes)), e_input, 10));
  1097.       sb_move (filewin, 2, 69);
  1098.       sb_puts (filewin, j);
  1099.       elapse_time ();
  1100.       sb_show ();
  1101.       }
  1102.    else
  1103.       {
  1104.       gotoxy (locate_x, locate_y);
  1105.       cputs (ultoa (((unsigned long) (*rxbytes)), e_input, 10));
  1106.       gotoxy (locate_x + 20, locate_y);
  1107.       printf ("%s", j);
  1108.       putch (' ');
  1109.       }
  1110.    return OK;
  1111.  
  1112. oops:
  1113.    got_error (msgtxt[M_WRITE_MSG], Filename);
  1114.    return ERROR;
  1115.  
  1116. }                                                 /* RZ_SaveToDisk */
  1117.  
  1118. /*--------------------------------------------------------------------------*/
  1119. /* RZ ACK BIBI                                                                */
  1120. /* Ack a ZFIN packet, let byegones be byegones                                */
  1121. /*--------------------------------------------------------------------------*/
  1122. static void RZ_AckBibi ()
  1123. {
  1124.    register int n;
  1125.  
  1126.  
  1127. #ifdef DEBUG
  1128.    show_debug_name ("RZ_AckBiBi");
  1129. #endif
  1130.  
  1131.    Z_PutLongIntoHeader (0L);
  1132.    for (n = 4; --n;)
  1133.       {
  1134.       Z_SendHexHeader (ZFIN, Txhdr);
  1135.       switch (Z_GetByte (100))
  1136.          {
  1137.          case 'O':
  1138.             Z_GetByte (1);                         /* Discard 2nd 'O' */
  1139.  
  1140.          case TIMEOUT:
  1141.          case RCDO:
  1142.             return;
  1143.          }                                         /* switch */
  1144.       }                                          /* for */
  1145. }                                                 /* RZ_AckBibi */
  1146. 
  1147.