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