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