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