home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / DOOR / BD2K260A.ZIP / SRC.ZIP / SRC / HYDRA.C < prev    next >
C/C++ Source or Header  |  1998-10-02  |  62KB  |  2,279 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. /*              This module was contributed by Michael Buenter              */
  13. /*                   Based on original code by Arjen Lentz                  */
  14. /*                    HydraCom adaptation for BinkleyTerm                   */
  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.  
  44. /*=============================================================================
  45.  
  46.                               HydraCom Version 1.08
  47.                              (+ rev. upto 18 dec 93)
  48.  
  49.                          A sample implementation of the
  50.                    HYDRA Bi-Directional File Transfer Protocol
  51.  
  52.                              HydraCom was written by
  53.                    Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT
  54.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  55.  
  56.                        The HYDRA protocol was designed by
  57.                  Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT and
  58.                             Joaquim H. Homrighausen
  59.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  60.  
  61.  
  62.   Revision history:
  63.   06 Sep 1991 - (AGL) First tryout
  64.   .. ... .... - Internal development
  65.   11 Jan 1993 - HydraCom version 1.00, Hydra revision 001 (01 Dec 1992)
  66.   13 Mar 1993 - HydraCom version 1.03, Hydra revision 001 (01 Dec 1992)
  67.   ..
  68.   Changes made by Michael Buenter:
  69.   03 Dec 1993 - adapted hydra for BT-EE and BT 2.58, many changes
  70.   ..
  71.   Updated source fixes by Arjen Lentz:
  72.   04 Sep 1993 - HydraCom version 1.08, Hydra revision 001 (01 Dec 1992)
  73.   23 Dec 1993 - updated to post-1.08 revisions upto 18 Dec 1993
  74.  
  75.   For complete details of the Hydra and HydraCom licensing restrictions,
  76.   please refer to the license agreements which are published in their entirety
  77.   in HYDRACOM.C and LICENSE.DOC, and also contained in the documentation file
  78.   HYDRACOM.DOC
  79.  
  80.   Use of this file is subject to the restrictions contained in the Hydra and
  81.   HydraCom licensing agreements. If you do not find the text of this agreement
  82.   in any of the aforementioned files, or if you do not have these files, you
  83.   should immediately contact LENTZ SOFTWARE-DEVELOPMENT and/or Joaquim
  84.   Homrighausen at one of the addresses listed below. In no event should you
  85.   proceed to use this file without having accepted the terms of the Hydra and
  86.   HydraCom licensing agreements, or such other agreement as you are able to
  87.   reach with LENTZ SOFTWARE-DEVELOMENT and Joaquim Homrighausen.
  88.  
  89.  
  90.   Hydra protocol design and HydraCom driver:         Hydra protocol design:
  91.   Arjen G. Lentz                                     Joaquim H. Homrighausen
  92.   LENTZ SOFTWARE-DEVELOPMENT                         389, route d'Arlon
  93.   Langegracht 7B                                     L-8011 Strassen
  94.   3811 BT  Amersfoort                                Luxembourg
  95.   The Netherlands
  96.   FidoNet 2:283/512, AINEX-BBS +31-33-633916         FidoNet 2:270/17
  97.   arjen_lentz@f512.n283.z2.fidonet.org               joho@ae.lu
  98.  
  99.   Please feel free to contact us at any time to share your comments about our
  100.   software and/or licensing policies.
  101.  
  102. =============================================================================*/
  103.  
  104. #include "includes.h"
  105. #include "hydra.h"
  106. #include "aglcrc.h"
  107.  
  108. /* external prototypes from janus.c */
  109. void j_status (char *,...);
  110. void j_msgend (word);
  111. void j_message (word, char *,...);
  112. int j_error (char *, char *);
  113. void xfer_summary (char *, char *, long *, int);
  114. void update_status (long *, long *, long, int *, int);
  115. long through (long *, long *);
  116.  
  117. int xfer_init (char *fname, long fsize, long ftime);
  118. int xfer_okay (void);
  119.  
  120. #define inteli(x) (x)
  121. #define intell(x) (x)
  122.  
  123. /* HYDRA's memory ---------------------------------------------------------- */
  124. static BOOL originator;                        /* are we the orig side?     */
  125. static int batchesdone;                        /* No. HYDRA batches done    */
  126. static BOOL hdxlink;                        /* hdx link & not orig side  */
  127. static ULONG options;                        /* INIT options hydra_init() */
  128. static word timeout;                        /* general timeout in secs   */
  129. static char abortstr[] =
  130. {24, 24, 24, 24, 24, 24, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0};
  131.  
  132. #ifdef HYDRADEV
  133. static char *hdxmsg = "Fallback to one-way xfer";
  134.  
  135. #endif
  136. static char *pktprefix = "";
  137. static char *autostr = "hydra\r";
  138. static word *crc16tab;                        /* CRC-16 table              */
  139. static ULONG *crc32tab;                        /* CRC-32 table              */
  140. static char *GenericError = "!%s";
  141.  
  142. static byte *txbuf, *rxbuf;                    /* packet buffers            */
  143. static ULONG txoptions, rxoptions;            /* HYDRA options (INIT seq)  */
  144. static char txpktprefix[H_PKTPREFIX + 1];    /* pkt prefix str they want  */
  145. static long txwindow, rxwindow;                /* window size (0=streaming) */
  146. static h_timer braindead;                    /* braindead timer           */
  147. static byte *txbufin;                        /* read data from disk here  */
  148. static byte txlastc;                        /* last byte put in txbuf    */
  149. static byte rxdle;                            /* count of received H_DLEs  */
  150. static byte rxpktformat;                    /* format of pkt receiving   */
  151. static byte *rxbufptr;                        /* current position in rxbuf */
  152. static byte *rxbufmax;                        /* highwatermark of rxbuf    */
  153. static char txfname[13], rxfname[13];        /* fname of current files    */
  154. static char rxpathname[PATHLEN];            /* pathname of currrent file */
  155. static long txftime, rxftime;                /* file timestamp (UNIX)     */
  156. static long txfsize, rxfsize;                /* file length               */
  157. static int txfd, rxfd;                        /* file handles              */
  158. static word rxpktlen;                        /* length of last packet     */
  159. static word rxblklen;                        /* len of last good data blk */
  160. static int txstate, rxstate;                /* xmit/recv states          */
  161. static long txpos, rxpos;                    /* current position in files */
  162. static long txoldpos, rxoldpos;                /* last position in files    */
  163. static word txblklen;                        /* length of last block sent */
  164. static word txmaxblklen;                    /* max block length allowed  */
  165. static long txlastack;                        /* last dataack received     */
  166. static long txstart, rxstart;                /* time we started this file */
  167. static int txoldeta, rxoldeta;                /* last time needed          */
  168. static long txoffset, rxoffset;                /* offset in file we begun   */
  169. static h_timer txtimer, rxtimer;            /* retry timers              */
  170. static word txretries, rxretries;            /* retry counters            */
  171. static long rxlastsync;                        /* filepos last sync retry   */
  172. static long txsyncid, rxsyncid;                /* id of last resync         */
  173. static word txgoodneeded;                    /* to send before larger blk */
  174. static word txgoodbytes;                    /* no. sent at this blk size */
  175.  
  176. struct _h_flags
  177. {
  178.     char *str;
  179.     ULONG val;
  180. };
  181.  
  182. static struct _h_flags h_flags[] =
  183. {
  184.     {"XON", HOPT_XONXOFF},
  185.     {"TLN", HOPT_TELENET},
  186.     {"CTL", HOPT_CTLCHRS},
  187.     {"HIC", HOPT_HIGHCTL},
  188.     {"HI8", HOPT_HIGHBIT},
  189.     {"BRK", HOPT_CANBRK},
  190.     {"ASC", HOPT_CANASC},
  191.     {"UUE", HOPT_CANUUE},
  192.     {"C32", HOPT_CRC32},
  193.     {"DEV", HOPT_DEVICE},
  194.     {"FPT", HOPT_FPT},
  195.     {NULL, 0x0L}
  196. };
  197.  
  198. /*-------------------------------------------------------------------------*/
  199. static int Next_y;        /* Number of next available line on screen         */
  200. static int Tx_y;        /* Line number of file transmission status display */
  201. static int Rx_y;        /* Line number of file reception status display    */
  202.  
  203. static char *
  204. h_revdate (long revstamp)
  205. {
  206.     static char buf[12];
  207.     struct tm *t;
  208.  
  209.     /* [Y2K] Ok as is.  Year was already 4 digits.
  210.      */
  211.     t = localtime (&revstamp);
  212.     sprintf (buf, "%02d %s %d",
  213.         t->tm_mday, mtext[t->tm_mon], t->tm_year + 1900);
  214.  
  215.     return (buf);
  216. }                                            /*h_revdate()*/
  217.  
  218. #ifdef HYDRADEV
  219. /*---------------------------------------------------------------------------*/
  220. static void 
  221. hydra_msgdev (byte * data, word len)
  222. {                                /* text is already NUL terminated by calling func hydra_devrecv() */
  223.     len = len;
  224.     j_status ("*HMSGDEV: %s", data);
  225. }                                /*hydra_msgdev()*/
  226.  
  227. /*---------------------------------------------------------------------------*/
  228. static int devtxstate;                        /* dev xmit state            */
  229. static h_timer devtxtimer;                    /* dev xmit retry timer      */
  230. static word devtxretries;                    /* dev xmit retry counter    */
  231. static long devtxid, devrxid;                /* id of last devdata pkt    */
  232. static char devtxdev[H_FLAGLEN + 1];        /* xmit device ident flag    */
  233. static byte *devtxbuf;                        /* ptr to usersupplied dbuf  */
  234. static word devtxlen;                        /* len of data in xmit buf   */
  235.  
  236. struct _h_dev
  237. {
  238.     char *dev;
  239.     void (*func) (byte * data, word len);
  240. };
  241.  
  242. static struct _h_dev h_dev[] =
  243. {
  244.     {"MSG", hydra_msgdev},                    /* internal protocol msg     */
  245.     {"CON", NULL},                            /* text to console (chat)    */
  246.     {"PRN", NULL},                            /* data to printer           */
  247.     {"ERR", NULL},                            /* text to error output      */
  248.     {NULL, NULL}
  249. };
  250.  
  251. /*---------------------------------------------------------------------------*/
  252. BOOL 
  253. hydra_devfree (void)
  254. {
  255.     if (devtxstate || !(txoptions & HOPT_DEVICE) || txstate >= HTX_END)
  256.         return (FALSE);                        /* busy or not allowed       */
  257.     else
  258.         return (TRUE);                        /* allowed to send a new pkt */
  259. }                                            /*hydra_devfree()*/
  260.  
  261. /*---------------------------------------------------------------------------*/
  262. BOOL 
  263. hydra_devsend (char *dev, byte * data, word len)
  264. {
  265.     if (!dev || !data || !len || !hydra_devfree ())
  266.         return (FALSE);
  267.  
  268.     strncpy (devtxdev, dev, H_FLAGLEN);
  269.     devtxdev[H_FLAGLEN] = '\0';
  270.     strupr (devtxdev);
  271.     devtxbuf = data;
  272.     devtxlen = (len > H_MAXBLKLEN) ? H_MAXBLKLEN : len;
  273.  
  274.     devtxid++;
  275.     devtxtimer = h_timer_reset ();
  276.     devtxretries = 0;
  277.     devtxstate = HTD_DATA;
  278.  
  279.     return (TRUE);
  280. }                                            /*hydra_devsend()*/
  281.  
  282. /*---------------------------------------------------------------------------*/
  283. BOOL 
  284. hydra_devfunc (char *dev, void (*func) (byte * data, word len))
  285. {
  286.     register int i;
  287.  
  288.     for (i = 0; h_dev[i].dev; i++)
  289.     {
  290.         if (!strnicmp (dev, h_dev[i].dev, H_FLAGLEN))
  291.         {
  292.             h_dev[i].func = func;
  293.             return (TRUE);
  294.         }
  295.     }
  296.  
  297.     return (FALSE);
  298. }                                            /*hydra_devfunc()*/
  299.  
  300. /*---------------------------------------------------------------------------*/
  301. static void 
  302. hydra_devrecv (void)
  303. {
  304.     register char *p = (char *) rxbuf;
  305.     register int i;
  306.     word len = rxpktlen;
  307.  
  308.     p += (int) sizeof (long);                        /* skip the id long  */
  309.     len -= (int) sizeof (long);
  310.  
  311.     for (i = 0; h_dev[i].dev; i++)
  312.     {                                                /* walk through devs */
  313.         if (!strncmp (p, h_dev[i].dev, H_FLAGLEN))
  314.         {
  315.             if (h_dev[i].func)
  316.             {
  317.                 len -= ((int) strlen (p)) + 1;        /* sub devstr len    */
  318.                 p += ((int) strlen (p)) + 1;        /* skip devtag       */
  319.                 p[len] = '\0';                        /* NUL terminate     */
  320.                 (*h_dev[i].func) ((byte *) p, len);    /* call output func  */
  321.             }
  322.             break;
  323.         }
  324.     }
  325. }                                                    /*hydra_devrecv()*/
  326.  
  327. #endif
  328.  
  329. /*---------------------------------------------------------------------------*/
  330. int 
  331. xfer_init (char *fname, long fsize, long ftime)
  332. {
  333.     int i;
  334.     char namebuf[PATHLEN];
  335.  
  336.     Resume_WaZOO = 0;
  337.  
  338.     strcpy (rxpathname, remote_capabilities ? CURRENT.sc_Inbound : download_path);
  339.     strcat (rxpathname, fname);
  340.  
  341.     /*--------------------------------------------------------------------*/
  342.     /* Save info on WaZOO transfer in case of abort                       */
  343.     /*--------------------------------------------------------------------*/
  344.     if (remote_capabilities)
  345.     {
  346.         (void) strcpy (Resume_name, fname);
  347.         (void) sprintf (Resume_info, "%ld %lo", fsize, ftime);
  348.     }
  349.  
  350.     /*--------------------------------------------------------------------*/
  351.     /* Check if this is a failed WaZOO transfer which should be resumed   */
  352.     /*--------------------------------------------------------------------*/
  353.     if (remote_capabilities && dexists (Abortlog_name))
  354.     {
  355.         Resume_WaZOO = (byte) check_failed (Abortlog_name, fname, Resume_info, namebuf);
  356.     }
  357.  
  358.     if (Resume_WaZOO)
  359.     {
  360.         strcpy (rxpathname, CURRENT.sc_Inbound);
  361.         strcat (rxpathname, namebuf);
  362.     }
  363.     else
  364.     {
  365.         if (dexists (rxpathname))
  366.         {
  367.             struct stat f;
  368.  
  369.             stat (rxpathname, &f);
  370.             if (fsize == f.st_size && ftime == f.st_mtime)
  371.                 return (FALSE);    /* already have file */
  372.             else
  373.             {
  374.                 i = strlen (rxpathname) - 1;
  375.                 if ((!overwrite) || (is_arcmail (rxpathname, i)))
  376.                 {
  377.                     unique_name (rxpathname);
  378.                 }
  379.                 else
  380.                 {
  381.                     (void) unlink (rxpathname);
  382.                 }
  383.             }
  384.         }                                    /* if exist */
  385.     }                                        /* Resume_WaZOO */
  386.  
  387.     return (TRUE);
  388. }                                            /*xfer_init()*/
  389.  
  390. /*---------------------------------------------------------------------------*/
  391. int 
  392. xfer_okay (void)
  393. {
  394.     static char new_pathname[PATHLEN];
  395.     char *p;
  396.  
  397.     remove_abort (Abortlog_name, Resume_name);
  398.     strcpy (new_pathname, CURRENT.sc_Inbound);
  399.     p = new_pathname + ((int) strlen (new_pathname));    /* start of fname */
  400.     strcat (new_pathname, Resume_name);                    /* add real fname */
  401.     unique_name (new_pathname);                            /* make it unique */
  402.     if (rename (rxpathname, new_pathname))                /* rename temp to real */
  403.         status_line ("!Could not rename '%s' to '%s'", rxpathname, new_pathname);
  404.     strcpy (rxpathname, new_pathname);
  405.     return (stricmp (p, Resume_name));                    /* dup rename? */
  406. }
  407.  
  408. /*---------------------------------------------------------------------------*/
  409. static void 
  410. put_flags (char *buf, struct _h_flags flags[], long val)
  411. {
  412.     register char *p;
  413.     register int i;
  414.  
  415.     p = buf;
  416.     for (i = 0; flags[i].val; i++)
  417.     {
  418.         if (val & flags[i].val)
  419.         {
  420.             if (p > buf)
  421.                 *p++ = ',';
  422.             strcpy (p, flags[i].str);
  423.             p += H_FLAGLEN;
  424.         }
  425.     }
  426.     *p = '\0';
  427. }                                            /*put_flags()*/
  428.  
  429. /*---------------------------------------------------------------------------*/
  430. static ULONG 
  431. get_flags (char *buf, struct _h_flags flags[])
  432. {
  433.     register ULONG val;
  434.     register char *p;
  435.     register int i;
  436.  
  437.     val = 0x0L;
  438.     for (p = strtok (buf, ","); p; p = strtok (NULL, ","))
  439.     {
  440.         for (i = 0; flags[i].val; i++)
  441.         {
  442.             if (!strcmp (p, flags[i].str))
  443.             {
  444.                 val |= flags[i].val;
  445.                 break;
  446.             }
  447.         }
  448.     }
  449.     return (val);
  450. }                                            /*get_flags()*/
  451.  
  452. /*---------------------------------------------------------------------------*/
  453. /* CRC-16/32 code now separate source *//*AGL:10mar93*/
  454.  
  455. /*---------------------------------------------------------------------------*/
  456. static byte *
  457. put_binbyte (register byte * p, register byte c)
  458. {
  459.     register byte n;
  460.  
  461.     n = c;
  462.     if (txoptions & HOPT_HIGHCTL)
  463.         n &= 0x7f;
  464.  
  465.     if (n == H_DLE ||
  466.         ((txoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  467.         ((txoptions & HOPT_TELENET) && n == '\r' && txlastc == '@') ||
  468.         ((txoptions & HOPT_CTLCHRS) && (n < 32 || n == 127)))
  469.     {
  470.         *p++ = H_DLE;
  471.         c ^= 0x40;
  472.     }
  473.  
  474.     *p++ = c;
  475.     txlastc = n;
  476.  
  477.     return (p);
  478. }                                            /*put_binbyte()*/
  479.  
  480. /*---------------------------------------------------------------------------*/
  481. static void 
  482. txpkt (register word len, int type)
  483. {
  484.     register byte *in, *out;
  485.     register word c, n;
  486.     BOOL crc32 = FALSE;
  487.     byte format;
  488.     static char hexdigit[] = "0123456789abcdef";
  489.  
  490.     txbufin[len++] = (byte)type;
  491.  
  492.     switch (type)
  493.     {
  494.     case HPKT_START:
  495.     case HPKT_INIT:
  496.     case HPKT_INITACK:
  497.     case HPKT_END:
  498.     case HPKT_IDLE:
  499.         format = HCHR_HEXPKT;
  500.         break;
  501.  
  502.     default:
  503.         /* COULD do smart format selection depending on data and options! */
  504.         if (txoptions & HOPT_HIGHBIT)
  505.         {
  506.             if ((txoptions & HOPT_CTLCHRS) && (txoptions & HOPT_CANUUE))
  507.                 format = HCHR_UUEPKT;
  508.             else if (txoptions & HOPT_CANASC)
  509.                 format = HCHR_ASCPKT;
  510.             else
  511.                 format = HCHR_HEXPKT;
  512.         }
  513.         else
  514.             format = HCHR_BINPKT;
  515.         break;
  516.     }
  517.  
  518.     if (format != HCHR_HEXPKT && (txoptions & HOPT_CRC32))
  519.         crc32 = TRUE;
  520.  
  521. #ifdef DEBUG
  522.     if (debugging_log)
  523.     {
  524.         char *s1, *s2, *s3, *s4;
  525.  
  526.         j_status (">-> PKT (format='%c'  type='%c'  crc=%d  len=%d)",
  527.             (char) format, (char) type, crc32 ? 32 : 16, (int) len - 1);
  528.  
  529.         switch (type)
  530.         {
  531.         case HPKT_START:
  532.             j_status (">   <autostr>START");
  533.             break;
  534.         case HPKT_INIT:
  535.             s1 = ((char *) txbufin) + ((int) strlen ((char *) txbufin)) + 1;
  536.             s2 = s1 + ((int) strlen (s1)) + 1;
  537.             s3 = s2 + ((int) strlen (s2)) + 1;
  538.             s4 = s3 + ((int) strlen (s3)) + 1;
  539.             /*                          j_status(">   INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  540.                                        (char *) txbufin, s1, s2, s3, s4); */
  541.             break;
  542.         case HPKT_INITACK:
  543.             j_status (">   INITACK");
  544.             break;
  545.         case HPKT_FINFO:
  546.             j_status (">   FINFO (%s)", txbufin);
  547.             break;
  548.         case HPKT_FINFOACK:
  549.             if (rxfd >= 0)
  550.             {
  551.                 if (rxpos > 0L)
  552.                     s1 = "RES";
  553.                 else
  554.                     s1 = "BOF";
  555.             }
  556.             else if (rxpos == -1L)
  557.                 s1 = "HAVE";
  558.             else if (rxpos == -2L)
  559.                 s1 = "SKIP";
  560.             else
  561.                 s1 = "EOB";
  562.             j_status (">   FINFOACK (pos=%ld %s  rxstate=%d  rxfd=%d)",
  563.                 rxpos, s1, (int) rxstate, rxfd);
  564.             break;
  565.         case HPKT_DATA:
  566.             j_status (">   DATA (ofs=%ld  len=%d)",
  567.                 intell (h_long1 (txbufin)), (int) len - 5);
  568.             break;
  569.         case HPKT_DATAACK:
  570.             j_status (">   DATAACK (ofs=%ld)",
  571.                 intell (h_long1 (txbufin)));
  572.             break;
  573.         case HPKT_RPOS:
  574.             j_status (">   RPOS (pos=%ld%s  blklen=%ld  syncid=%ld)",
  575.                 rxpos, rxpos < 0L ? " SKIP" : "",
  576.                 intell (h_long2 (txbufin)), rxsyncid);
  577.             break;
  578.         case HPKT_EOF:
  579.             j_status (">   EOF (ofs=%ld%s)",
  580.                 txpos, txpos < 0L ? " SKIP" : "");
  581.             break;
  582.         case HPKT_EOFACK:
  583.             j_status (">   EOFACK");
  584.             break;
  585.         case HPKT_IDLE:
  586.             j_status (">   IDLE");
  587.             break;
  588.         case HPKT_END:
  589.             j_status (">   END");
  590.             break;
  591. #ifdef HYDRADEV
  592.         case HPKT_DEVDATA:
  593.             j_status (">   DEVDATA (id=%ld  dev='%s'  len=%hu)",
  594.                 devtxid, devtxdev, devtxlen);
  595.             break;
  596.         case HPKT_DEVDACK:
  597.             j_status (">   DEVDACK (id=%ld)",
  598.                 intell (h_long1 (rxbuf)));
  599.             break;
  600. #endif
  601.         default:                /* This couldn't possibly happen! ;-) */
  602.             break;
  603.         }
  604.     }
  605. #endif
  606.  
  607.     if (crc32)
  608.     {
  609.         ULONG crc = CRC32POST (crc32block (crc32tab, CRC32INIT, txbufin, len));    /*AGL:10mar93*/
  610.  
  611.         txbufin[len++] = (byte) crc;
  612.         txbufin[len++] = (byte) (crc >> 8);
  613.         txbufin[len++] = (byte) (crc >> 16);
  614.         txbufin[len++] = (byte) (crc >> 24);
  615.     }
  616.     else
  617.     {
  618.         word crc = CRC16POST (crc16block (crc16tab, CRC16INIT, txbufin, len));    /*AGL:10mar93*/
  619.  
  620.         txbufin[len++] = (byte) crc;
  621.         txbufin[len++] = (byte) (crc >> 8);
  622.     }
  623.  
  624.     in = txbufin;
  625.     out = txbuf;
  626.     txlastc = 0;
  627.     *out++ = H_DLE;
  628.     *out++ = format;
  629.  
  630.     switch (format)
  631.     {
  632.     case HCHR_HEXPKT:
  633.         for (; len > 0; len--, in++)
  634.         {
  635.             if (*in & 0x80)
  636.             {
  637.                 *out++ = '\\';
  638.                 *out++ = hexdigit[((*in) >> 4) & 0x0f];
  639.                 *out++ = hexdigit[(*in) & 0x0f];
  640.             }
  641.             else if (*in < 32 || *in == 127)
  642.             {
  643.                 *out++ = H_DLE;
  644.                 *out++ = (byte)((*in) ^ 0x40);
  645.             }
  646.             else if (*in == '\\')
  647.             {
  648.                 *out++ = '\\';
  649.                 *out++ = '\\';
  650.             }
  651.             else
  652.                 *out++ = *in;
  653.         }
  654.         break;
  655.  
  656.     case HCHR_BINPKT:
  657.         for (; len > 0; len--)
  658.             out = put_binbyte (out, *in++);
  659.         break;
  660.  
  661.     case HCHR_ASCPKT:
  662.         for (n = c = 0; len > 0; len--)
  663.         {
  664.             c |= ((*in++) << n);
  665.             out = put_binbyte (out, (byte)(c & 0x7f));
  666.             c >>= 7;
  667.             if (++n >= 7)
  668.             {
  669.                 out = put_binbyte (out, (byte)(c & 0x7f));
  670.                 n = c = 0;
  671.             }
  672.         }
  673.         if (n > 0)
  674.             out = put_binbyte (out, (byte)(c & 0x7f));
  675.         break;
  676.  
  677.     case HCHR_UUEPKT:
  678.         for (; len >= 3; in += 3, len -= 3)
  679.         {
  680.             *out++ = (byte) h_uuenc (in[0] >> 2);
  681.             *out++ = (byte) h_uuenc (((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  682.             *out++ = (byte) h_uuenc (((in[1] << 2) & 0x3c) | ((in[2] >> 6) & 0x03));
  683.             *out++ = (byte) h_uuenc (in[2] & 0x3f);
  684.         }
  685.         if (len > 0)
  686.         {
  687.             *out++ = (byte) h_uuenc (in[0] >> 2);
  688.             *out++ = (byte) h_uuenc (((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  689.             if (len == 2)
  690.                 *out++ = (byte) h_uuenc ((in[1] << 2) & 0x3c);
  691.         }
  692.         break;
  693.     }
  694.  
  695.     *out++ = H_DLE;
  696.     *out++ = HCHR_PKTEND;
  697.  
  698.     if (type != HPKT_DATA && format != HCHR_BINPKT)
  699.     {
  700.         *out++ = '\r';
  701.         *out++ = '\n';
  702.     }
  703.  
  704.     for (in = (byte *) txpktprefix; *in; in++)
  705.     {
  706.         switch (*in)
  707.         {
  708.         case 221:                /* transmit break signal for one second */
  709.             do_break(TRUE);
  710.             {
  711.                 h_timer t = h_timer_set (2);
  712.                 while (!h_timer_expired (t, h_timer_get ()))
  713.                     time_release ();
  714.             }
  715.             do_break(FALSE);
  716.             break;
  717.         case 222:
  718.             {
  719.                 h_timer t = h_timer_set (2);
  720.  
  721.                 while (!h_timer_expired (t, h_timer_get ()))
  722.                     time_release ();
  723.             }
  724.             break;
  725.         case 223:
  726.             SENDBYTE (0);
  727.             break;
  728.         default:
  729.             SENDBYTE (*in);
  730.             break;
  731.         }
  732.     }
  733.  
  734.     ComTXBlockTimeout (txbuf, (USHORT) (out - txbuf), braindead);
  735. }                                /*txpkt()*/
  736.  
  737. /*---------------------------------------------------------------------------*/
  738. static int 
  739. rxpkt (void)
  740. {
  741.     register byte *p, *q = rxbuf;
  742.     register word n, i;
  743.     short c;
  744.     h_timer tnow = h_timer_get ();    /*AGL:16jul93*/
  745.  
  746.     if (got_ESC ())
  747.         return (H_SYSABORT);
  748.     if (!CARRIER)
  749.         return (H_CARRIER);
  750.  
  751.     if (h_timer_running (braindead) && h_timer_expired (braindead, tnow))
  752.     {
  753. #ifdef DEBUG
  754.         if (debugging_log)
  755.             j_status (" <- BrainDead (timer=%08lx  time=%08lx)", braindead, tnow);
  756. #endif
  757.         return (H_BRAINTIME);
  758.     }
  759.  
  760.     if (h_timer_running (txtimer) && h_timer_expired (txtimer, tnow))
  761.     {
  762. #ifdef DEBUG
  763.         if (debugging_log)
  764.             j_status (" <- TxTimer (timer=%08lx  time=%08lx)", txtimer, tnow);
  765. #endif
  766.         return (H_TXTIME);
  767.     }
  768.  
  769. #ifdef HYDRADEV
  770.     if (h_timer_running (devtxtimer) && h_timer_expired (devtxtimer, tnow))
  771.     {
  772. #ifdef DEBUG
  773.         if (debugging_log)
  774.             j_status (" <- DevTxTimer (timer=%08lx  time=%08lx)", devtxtimer, time (NULL));
  775. #endif
  776.         return (H_DEVTXTIME);
  777.     }
  778. #endif
  779.  
  780.     p = rxbufptr;
  781.  
  782.     while (CHAR_AVAIL ())
  783.     {
  784.         c = MODEM_IN ();
  785.         if (rxoptions & HOPT_HIGHBIT)
  786.             c &= 0x7f;
  787.  
  788.         n = c;
  789.         if (rxoptions & HOPT_HIGHCTL)
  790.             n &= 0x7f;
  791.         if (n != H_DLE &&
  792.             (((rxoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  793.                 ((rxoptions & HOPT_CTLCHRS) && (n < 32 || n == 127))))
  794.             continue;
  795.  
  796.         if (rxdle || c == H_DLE)
  797.         {
  798.             switch (c)
  799.             {
  800.             case H_DLE:
  801.                 if (++rxdle >= 5)
  802.                     return (H_CANCEL);
  803.                 break;
  804.  
  805.             case HCHR_PKTEND:
  806.                 rxbufptr = p;
  807.  
  808.                 switch (rxpktformat)
  809.                 {
  810.                 case HCHR_BINPKT:
  811.                     q = rxbufptr;
  812.                     break;
  813.  
  814.                 case HCHR_HEXPKT:
  815.                     for (p = q = rxbuf; p < rxbufptr; p++)
  816.                     {
  817.                         if (*p == '\\' && *++p != '\\')
  818.                         {
  819.                             i = *p;
  820.                             n = *++p;
  821.                             if ((i -= '0') > 9)
  822.                                 i -= ('a' - ':');
  823.                             if ((n -= '0') > 9)
  824.                                 n -= ('a' - ':');
  825.                             if ((i & ~0x0f) || (n & ~0x0f))
  826.                             {
  827.                                 c = H_NOPKT;
  828.                                 break;
  829.                             }
  830.                             *q++ = (byte) ((i << 4) | n);
  831.                         }
  832.                         else
  833.                             *q++ = *p;
  834.                     }
  835.                     if (p > rxbufptr)
  836.                         c = H_NOPKT;
  837.                     break;
  838.  
  839.                 case HCHR_ASCPKT:
  840.                     n = i = 0;
  841.                     for (p = q = rxbuf; p < rxbufptr; p++)
  842.                     {
  843.                         i |= ((*p & 0x7f) << n);
  844.                         if ((n += 7) >= 8)
  845.                         {
  846.                             *q++ = (byte) (i & 0xff);
  847.                             i >>= 8;
  848.                             n -= 8;
  849.                         }
  850.                     }
  851.                     break;
  852.  
  853.                 case HCHR_UUEPKT:
  854.                     n = (int) (rxbufptr - rxbuf);
  855.                     for (p = q = rxbuf; n >= 4; n -= 4, p += 4)
  856.                     {
  857.                         if (p[0] <= ' ' || p[0] >= 'a' ||
  858.                             p[1] <= ' ' || p[1] >= 'a' ||
  859.                             p[2] <= ' ' || p[2] >= 'a' ||
  860.                             p[3] <= ' ' || p[3] >= 'a')
  861.                         {
  862.                             c = H_NOPKT;
  863.                             break;
  864.                         }
  865.                         *q++ = (byte) ((h_uudec (p[0]) << 2) | (h_uudec (p[1]) >> 4));
  866.                         *q++ = (byte) ((h_uudec (p[1]) << 4) | (h_uudec (p[2]) >> 2));
  867.                         *q++ = (byte) ((h_uudec (p[2]) << 6) | h_uudec (p[3]));
  868.                     }
  869.                     if (n >= 2)
  870.                     {
  871.                         if (p[0] <= ' ' || p[0] >= 'a' ||
  872.                             p[1] <= ' ' || p[1] >= 'a')
  873.                         {
  874.                             c = H_NOPKT;
  875.                             break;
  876.                         }
  877.                         *q++ = (byte) ((h_uudec (p[0]) << 2) | (h_uudec (p[1]) >> 4));
  878.                         if (n == 3)
  879.                         {
  880.                             if (p[2] <= ' ' || p[2] >= 'a')
  881.                             {
  882.                                 c = H_NOPKT;
  883.                                 break;
  884.                             }
  885.                             *q++ = (byte) ((h_uudec (p[1]) << 4) | (h_uudec (p[2]) >> 2));
  886.                         }
  887.                     }
  888.                     break;
  889.  
  890.                 default:        /* This'd mean internal fluke */
  891. #ifdef DEBUG
  892.                     if (debugging_log)
  893.                     {
  894.                         j_status (" <- <PKTEND> (pktformat='%c' dec=%d hex=%02x) ??",
  895.                             (char) rxpktformat, (int) rxpktformat, (int) rxpktformat);
  896.                     }
  897. #endif
  898.                     c = H_NOPKT;
  899.                     break;
  900.                 }
  901.  
  902.                 rxbufptr = NULL;
  903.  
  904.                 if (c == H_NOPKT)
  905.                     break;
  906.  
  907.                 rxpktlen = (word) (q - rxbuf);
  908.                 if (rxpktformat != HCHR_HEXPKT && (rxoptions & HOPT_CRC32))
  909.                 {
  910.                     if (rxpktlen < 5)
  911.                     {
  912.                         c = H_NOPKT;
  913.                         break;
  914.                     }
  915.                     n = h_crc32test (crc32block (crc32tab, CRC32INIT, rxbuf, rxpktlen));    /*AGL:10mar93*/
  916.                     rxpktlen -= (int) sizeof (long);    /* remove CRC-32 */
  917.                 }
  918.                 else
  919.                 {
  920.                     if (rxpktlen < 3)
  921.                     {
  922.                         c = H_NOPKT;
  923.                         break;
  924.                     }
  925.                     n = h_crc16test (crc16block (crc16tab, CRC16INIT, rxbuf, rxpktlen));    /*AGL:10mar93*/
  926.                     rxpktlen -= (int) sizeof (word);    /* remove CRC-16 */
  927.                 }
  928.  
  929.                 rxpktlen--;        /* remove type  */
  930.  
  931.                 if (n)
  932.                 {
  933. #ifdef DEBUG
  934.                     if (debugging_log)
  935.                     {
  936.                         char *s1, *s2, *s3, *s4;
  937.  
  938.                         j_status ("><- PKT (format='%c'  type='%c'  len=%hd)",
  939.                             (char) rxpktformat, rxbuf[rxpktlen], rxpktlen);
  940.  
  941.                         switch (rxbuf[rxpktlen])
  942.                         {
  943.                         case HPKT_START:
  944.                             j_status ("<   START");
  945.                             break;
  946.                         case HPKT_INIT:
  947.                             s1 = ((char *) rxbuf) + ((int) strlen ((char *) rxbuf)) + 1;
  948.                             s2 = s1 + ((int) strlen (s1)) + 1;
  949.                             s3 = s2 + ((int) strlen (s2)) + 1;
  950.                             s4 = s3 + ((int) strlen (s3)) + 1;
  951.                             /*                                          j_status("<   INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  952.                                                      (char *) rxbuf, s1, s2, s3, s4);  */
  953.                             break;
  954.                         case HPKT_INITACK:
  955.                             j_status ("<   INITACK");
  956.                             break;
  957.                         case HPKT_FINFO:
  958.                             j_status ("<   FINFO ('%s'  rxstate=%d)", rxbuf, (int) rxstate);
  959.                             break;
  960.                         case HPKT_FINFOACK:
  961.                             j_status ("<   FINFOACK (pos=%ld  txstate=%d  txfd=%d)",
  962.                                 intell (h_long1 (rxbuf)), (int) txstate, txfd);
  963.                             break;
  964.                         case HPKT_DATA:
  965.                             j_status ("<   DATA (rxstate=%d  pos=%ld  len=%hu)",
  966.                                 (int) rxstate, intell (h_long1 (rxbuf)),
  967.                                 (word) (rxpktlen - ((int) sizeof (long))));
  968.  
  969.                             break;
  970.                         case HPKT_DATAACK:
  971.                             j_status ("<   DATAACK (rxstate=%d  pos=%ld)",
  972.                                 (int) rxstate, intell (h_long1 (rxbuf)));
  973.                             break;
  974.                         case HPKT_RPOS:
  975.                             j_status ("<   RPOS (pos=%ld%s  blklen=%hu->%ld  syncid=%ld%s  txstate=%d  txfd=%d)",
  976.                                 intell (h_long1 (rxbuf)),
  977.                                 intell (h_long1 (rxbuf)) < 0L ? " SKIP" : "",
  978.                                 txblklen, intell (h_long2 (rxbuf)),
  979.                                 intell (h_long3 (rxbuf)),
  980.                                 intell (h_long3 (rxbuf)) == rxsyncid ? " DUP" : "",
  981.                                 (int) txstate, txfd);
  982.                             break;
  983.                         case HPKT_EOF:
  984.                             j_status ("<   EOF (rxstate=%d  pos=%ld%s)",
  985.                                 (int) rxstate, intell (h_long1 (rxbuf)),
  986.                                 intell (h_long1 (rxbuf)) < 0L ? " SKIP" : "");
  987.                             break;
  988.                         case HPKT_EOFACK:
  989.                             j_status ("<   EOFACK (txstate=%d)", (int) txstate);
  990.                             break;
  991.                         case HPKT_IDLE:
  992.                             j_status ("<   IDLE");
  993.                             break;
  994.                         case HPKT_END:
  995.                             j_status ("<   END");
  996.                             break;
  997. #ifdef HYDRADEV
  998.                         case HPKT_DEVDATA:
  999.                             s1 = ((char *) rxbuf) + ((int) sizeof (long));
  1000.  
  1001.                             j_status ("<   DEVDATA (id=%ld  dev=%s  len=%u",
  1002.                                 intell (h_long1 (rxbuf)), s1,
  1003.                                 (int) rxpktlen - (((int) sizeof (long)) + ((int) strlen (s1)) + 1));
  1004.  
  1005.                             break;
  1006.                         case HPKT_DEVDACK:
  1007.                             j_status ("<   DEVDACK (devtxstate=%d  id=%ld)",
  1008.                                 (int) devtxstate, intell (h_long1 (rxbuf)));
  1009.                             break;
  1010. #endif
  1011.                         default:
  1012.                             j_status ("<   Unkown pkttype %c (txstate=%d  rxstate=%d)",
  1013.                                 rxbuf[rxpktlen], (int) txstate, (int) rxstate);
  1014.                             break;
  1015.                         }
  1016.                     }
  1017. #endif
  1018.                     return ((int) rxbuf[rxpktlen]);
  1019.                 }                /*goodpkt*/
  1020.  
  1021. #ifdef DEBUG
  1022.                 if (debugging_log)
  1023.                     j_status (">Bad CRC (format='%c'  type='%c'  len=%d)",
  1024.                         (char) rxpktformat, rxbuf[rxpktlen], (int) rxpktlen);
  1025. #endif
  1026.                 break;
  1027.  
  1028.             case HCHR_BINPKT:
  1029.             case HCHR_HEXPKT:
  1030.             case HCHR_ASCPKT:
  1031.             case HCHR_UUEPKT:
  1032. #ifdef DEBUG
  1033.                 if (debugging_log)
  1034.                     j_status (" <- <PKTSTART> (pktformat='%c')", (char) c);
  1035. #endif
  1036.                 rxpktformat = (byte) c;
  1037.                 p = rxbufptr = rxbuf;
  1038.                 rxdle = 0;
  1039.                 break;
  1040.  
  1041.             default:
  1042.                 if (p)
  1043.                 {
  1044.                     if (p < rxbufmax)
  1045.                         *p++ = (byte) (c ^ 0x40);
  1046.                     else
  1047.                     {
  1048. #ifdef DEBUG
  1049.                         if (debugging_log)
  1050.                             j_status (" <- Pkt too long - discarded");
  1051. #endif
  1052.                         p = NULL;
  1053.                     }
  1054.                 }
  1055.                 rxdle = 0;
  1056.                 break;
  1057.             }                    /* case */
  1058.         }
  1059.         else if (p)
  1060.         {
  1061.             if (p < rxbufmax)
  1062.                 *p++ = (byte) c;
  1063.             else
  1064.             {
  1065. #ifdef DEBUG
  1066.                 if (debugging_log)
  1067.                     j_status (" <- Pkt too long - discarded");
  1068. #endif
  1069.                 p = NULL;
  1070.             }
  1071.         }
  1072.     }
  1073.  
  1074.     rxbufptr = p;
  1075.  
  1076.     time_release ();
  1077.     return (H_NOPKT);
  1078. }                                /*rxpkt()*/
  1079.  
  1080. /*---------------------------------------------------------------------------*/
  1081. void 
  1082. hydra_badxfer (void)
  1083. {
  1084.     if (rxfd >= 0)
  1085.     {
  1086.         close (rxfd);
  1087.         rxfd = -1;
  1088.         if (remote_capabilities)
  1089.         {
  1090.             if (!Resume_WaZOO)
  1091.             {
  1092.                 add_abort (Abortlog_name, Resume_name, rxpathname, CURRENT.sc_Inbound, Resume_info);
  1093.             }
  1094.         }
  1095.         else
  1096.         {
  1097.             (void) unlink (rxpathname);
  1098.         }
  1099.     }
  1100. }                                /*hydra_badxfer()*/
  1101.  
  1102. /*---------------------------------------------------------------------------*/
  1103. void 
  1104. hydra_init (ULONG want_options)
  1105. {
  1106.     char *HoldName;
  1107.  
  1108.     txbuf = Txbuf;
  1109.     rxbuf = txbuf + H_BUFLEN;
  1110.  
  1111.     crc16tab = (word *) malloc (CRC_TABSIZE * ((int) sizeof (word)));
  1112.     crc32tab = (ULONG *) malloc (CRC_TABSIZE * ((int) sizeof (ULONG)));
  1113.  
  1114.     if (!txbuf || !rxbuf || !crc16tab || !crc32tab)
  1115.     {
  1116.         status_line (MSG_TXT (M_MEM_ERROR));
  1117.         mdm_hangup ();
  1118.         return;
  1119.     }
  1120.     txbufin = txbuf + ((H_MAXBLKLEN + H_OVERHEAD + 5) * 2);
  1121.     rxbufmax = rxbuf + H_MAXPKTLEN;
  1122.  
  1123.     crc16init (crc16tab, CRC16POLY);
  1124.     crc32init (crc32tab, CRC32POLY);
  1125.  
  1126.     batchesdone = 0;
  1127.     mail_finished = 1;
  1128.  
  1129.     originator = remote_capabilities ? (isOriginator ? TRUE : FALSE) : TRUE;
  1130.  
  1131.     HoldName = HoldAreaNameMunge (&called_addr);
  1132.  
  1133.     (void) sprintf (Abortlog_name, "%s%s.Z\0",
  1134.         HoldName, Hex_Addr_Str (&remote_addr));
  1135.  
  1136.     if (originator)
  1137.         hdxlink = FALSE;
  1138.     else
  1139.         hdxlink = !((janus_baud >= cur_baud.rate_value) || (janus_OK));
  1140.  
  1141.     options = (want_options & HCAN_OPTIONS) & ~HUNN_OPTIONS;
  1142.  
  1143.     timeout = (word) (40960L / cur_baud.rate_value);
  1144.     if (timeout < H_MINTIMER)
  1145.         timeout = H_MINTIMER;
  1146.     else if (timeout > H_MAXTIMER)
  1147.         timeout = H_MAXTIMER;
  1148.  
  1149.     txmaxblklen = (short) ((cur_baud.rate_value / 300) * 128);
  1150.     if (txmaxblklen < 256)
  1151.         txmaxblklen = 256;
  1152.     else if (txmaxblklen > H_MAXBLKLEN)
  1153.         txmaxblklen = H_MAXBLKLEN;
  1154.  
  1155.     rxblklen = txblklen = (cur_baud.rate_value < 2400U) ? 256 : 512;
  1156.  
  1157.     txgoodbytes = 0;
  1158.     txgoodneeded = txmaxblklen;    /*AGL:23feb93*/
  1159.  
  1160.     txstate = HTX_DONE;
  1161.  
  1162.     set_prior (3);                /* Time Critical */
  1163.     XON_DISABLE ();
  1164.  
  1165.     if (un_attended && fullscreen)
  1166.     {
  1167.         clear_filetransfer ();
  1168.         sb_show ();
  1169.         Tx_y = 1;
  1170.         Rx_y = 2;
  1171.     }
  1172.     else
  1173.     {
  1174.         set_xy (NULL);
  1175.         Rx_y = Tx_y = Next_y = locate_y;
  1176.     }
  1177.  
  1178. }                                /*hydra_init()*/
  1179.  
  1180. /*---------------------------------------------------------------------------*/
  1181. void 
  1182. hydra_deinit (void)
  1183. {
  1184.     free (crc16tab);
  1185.     free (crc32tab);
  1186.  
  1187.     set_prior (4);                /* Always High */
  1188. }                                /*hydra_deinit()*/
  1189.  
  1190. /*---------------------------------------------------------------------------*/
  1191. int 
  1192. hydra (char *txpathname, char *txalias)
  1193. {
  1194.     int res = 0;
  1195.     int pkttype;
  1196.     char *p, *q;
  1197.     int i;
  1198.     struct stat f;
  1199.  
  1200.     /*-------------------------------------------------------------------*/
  1201.     if (txstate == HTX_DONE)
  1202.     {
  1203.         txstate = HTX_START;
  1204.         txoptions = HTXI_OPTIONS;
  1205.         txpktprefix[0] = '\0';
  1206.  
  1207.         rxstate = HRX_INIT;
  1208.         rxoptions = HRXI_OPTIONS;
  1209.         rxfd = -1;
  1210.         rxdle = 0;
  1211.         rxbufptr = NULL;
  1212.         rxtimer = h_timer_reset ();
  1213.  
  1214. #ifdef HYDRADEV
  1215.         devtxid = devrxid = 0L;
  1216.         devtxtimer = h_timer_reset ();
  1217.         devtxstate = HTD_DONE;
  1218. #endif
  1219.  
  1220.         braindead = h_timer_set (H_BRAINDEAD);
  1221.     }
  1222.     else
  1223.         txstate = HTX_FINFO;
  1224.  
  1225.     txtimer = h_timer_reset ();
  1226.     txretries = 0;
  1227.  
  1228.     /*-------------------------------------------------------------------*/
  1229.     if (txpathname)
  1230.     {
  1231.         stat (txpathname, &f);
  1232.         txfsize = f.st_size;
  1233.         txftime = f.st_mtime;
  1234.  
  1235.         if ((txfd = share_open (txpathname, O_RDONLY | O_BINARY, DENY_WRITE)) < 0)
  1236.         {
  1237.             j_error (MSG_TXT (M_OPEN_MSG), txpathname);
  1238.             return (XFER_SKIP);
  1239.         }
  1240.  
  1241.         if (isatty (txfd))
  1242.         {
  1243.             errno = 1;
  1244.             (void) j_error (MSG_TXT (M_DEVICE_MSG), txpathname);
  1245.             close (txfd);
  1246.             return (XFER_SKIP);
  1247.         }
  1248.  
  1249.         strupr (txpathname);
  1250.         for (p = txpathname, q = txfname; *p; p++)
  1251.         {
  1252.             if (*q = *p, *p == '\\' || *p == ':' || *p == '/')
  1253.                 q = txfname;
  1254.             else
  1255.                 q++;
  1256.         }
  1257.         *q = '\0';
  1258.  
  1259.         if (txalias)
  1260.             strupr (txalias);
  1261.  
  1262.         txstart = 0L;
  1263.         txsyncid = 0L;
  1264.     }
  1265.     else
  1266.     {
  1267.         txfd = -1;
  1268.         strcpy (txfname, "");
  1269.     }
  1270.  
  1271.     /*-------------------------------------------------------------------*/
  1272.     do
  1273.     {
  1274. #ifdef HYDRADEV
  1275.         /*----------------------------------------------------------------*/
  1276.         switch (devtxstate)
  1277.         {
  1278.             /*---------------------------------------------------------*/
  1279.         case HTD_DATA:
  1280.             if (txstate > HTX_RINIT)
  1281.             {
  1282.                 h_long1 (txbufin) = intell (devtxid);
  1283.                 p = ((char *) txbufin) + ((int) sizeof (long));
  1284.  
  1285.                 strcpy (p, devtxdev);
  1286.                 p += H_FLAGLEN + 1;
  1287.                 memcpy (p, devtxbuf, devtxlen);
  1288.                 txpkt (((int) sizeof (long)) + H_FLAGLEN + 1 + devtxlen, HPKT_DEVDATA);
  1289.  
  1290.                 devtxtimer = h_timer_set ((!rxstate && txstate == HTX_REND) ? timeout / 2 : timeout);    /*AGL:10mar93*/
  1291.                 devtxstate = HTD_DACK;
  1292.             }
  1293.             break;
  1294.  
  1295.             /*---------------------------------------------------------*/
  1296.         default:
  1297.             break;
  1298.  
  1299.             /*---------------------------------------------------------*/
  1300.         }
  1301. #endif
  1302.         /*----------------------------------------------------------------*/
  1303.         switch (txstate)
  1304.         {
  1305.             /*---------------------------------------------------------*/
  1306.         case HTX_START:
  1307.             SENDCHARS (autostr, (int) strlen (autostr), 1);
  1308.             txpkt (0, HPKT_START);
  1309.             txtimer = h_timer_set (H_START);
  1310.             txstate = HTX_SWAIT;
  1311.             break;
  1312.  
  1313.             /*---------------------------------------------------------*/
  1314.         case HTX_INIT:
  1315.             p = (char *) txbufin;
  1316.             sprintf (p, "%08lx%s,%s", H_REVSTAMP, PRDCT_PRTY, PRDCT_VRSN);
  1317.             p += ((int) strlen (p)) + 1;    /* our app info & HYDRA rev. */
  1318.             put_flags (p, h_flags, HCAN_OPTIONS);    /* what we CAN  */
  1319.             p += ((int) strlen (p)) + 1;
  1320.             put_flags (p, h_flags, options);    /* what we WANT */
  1321.             p += ((int) strlen (p)) + 1;
  1322.             sprintf (p, "%08lx%08lx",    /* TxRx windows */
  1323.                 hydra_txwindow, hydra_rxwindow);
  1324.             p += ((int) strlen (p)) + 1;
  1325.             strcpy (p, pktprefix);    /* pkt prefix string we want */
  1326.             p += ((int) strlen (p)) + 1;
  1327.  
  1328.             txoptions = HTXI_OPTIONS;
  1329.             txpkt ((word) (((byte *) p) - txbufin), HPKT_INIT);
  1330.             txoptions = rxoptions;
  1331.             txtimer = h_timer_set (timeout / 2);
  1332.             txstate = HTX_INITACK;
  1333.             break;
  1334.  
  1335.             /*---------------------------------------------------------*/
  1336.         case HTX_FINFO:
  1337.             if (txfd >= 0)
  1338.             {
  1339.                 if (!txretries)
  1340.                 {
  1341.                     txoldpos = txoldeta = -1;
  1342.                     if (!un_attended || !fullscreen)
  1343.                         Tx_y = Next_y;
  1344.                     if (txalias)
  1345.                         xfer_summary (MSG_TXT (M_SEND), txalias, &txfsize, Tx_y);
  1346.                     else
  1347.                         xfer_summary (MSG_TXT (M_SEND), txfname, &txfsize, Tx_y);
  1348.                     strlwr (txfname);
  1349.                 }
  1350.                 sprintf ((char *) txbufin, "%08lx%08lx%08lx%08lx%08lx%s",
  1351.                     txftime, txfsize, 0L, 0L, 0L,
  1352.                     txalias ? txalias : txfname);
  1353.             }
  1354.             else
  1355.             {
  1356.                 if (!txretries)
  1357.                 {
  1358.                     j_msgend (Tx_y);
  1359. #ifdef DEBUG
  1360.                     j_status ("+HSEND: End of batch");
  1361. #endif
  1362.                 }
  1363.                 strcpy ((char *) txbufin, txfname);
  1364.             }
  1365.             txpkt (((int) strlen ((char *) txbufin)) + 1, HPKT_FINFO);
  1366.             txtimer = h_timer_set (txretries ? timeout / 2 : timeout);
  1367.             txstate = HTX_FINFOACK;
  1368.             break;
  1369.  
  1370.             /*---------------------------------------------------------*/
  1371.         case HTX_XDATA:
  1372.             if (ComTXRemain () > txmaxblklen)
  1373.                 break;
  1374.  
  1375.             if (txpos < 0L)
  1376.                 i = -1;            /* Skip */
  1377.             else
  1378.             {
  1379.                 h_long1 (txbufin) = intell (txpos);
  1380.                 if ((i = read (txfd, txbufin + ((int) sizeof (long)), txblklen)) < 0)
  1381.                 {
  1382.                     j_error (MSG_TXT (M_READ_MSG), txfname);
  1383.                     close (txfd);
  1384.                     txfd = -1;
  1385.                     txpos = -2L;/* Skip */
  1386.                 }
  1387.             }
  1388.  
  1389.             if (i > 0)
  1390.             {
  1391.                 txpos += i;
  1392.                 txpkt (((int) sizeof (long)) + i, HPKT_DATA);
  1393.  
  1394.                 if (txblklen < txmaxblklen &&
  1395.                     (txgoodbytes += i) >= txgoodneeded)
  1396.                 {
  1397.                     txblklen <<= 1;
  1398.                     if (txblklen >= txmaxblklen)
  1399.                     {
  1400.                         txblklen = txmaxblklen;
  1401.                         txgoodneeded = 0;
  1402.                     }
  1403.                     txgoodbytes = 0;
  1404.                 }
  1405.  
  1406.                 if (txwindow && (txpos >= (txlastack + txwindow)))
  1407.                 {
  1408.                     txtimer = h_timer_set (txretries ? timeout / 2 : timeout);
  1409.                     txstate = HTX_DATAACK;
  1410.                 }
  1411.  
  1412.                 if (!txstart)
  1413.                     txstart = time (NULL);
  1414.                 update_status (&txpos, &txoldpos, txfsize - txpos, &txoldeta, Tx_y);
  1415.                 break;
  1416.             }
  1417.  
  1418.             /* fallthrough to HTX_EOF */
  1419.  
  1420.             /*---------------------------------------------------------*/
  1421.         case HTX_EOF:
  1422.             h_long1 (txbufin) = intell (txpos);
  1423.             txpkt ((int) sizeof (long), HPKT_EOF);
  1424.  
  1425.             txtimer = h_timer_set (txretries ? timeout / 2 : timeout);
  1426.             txstate = HTX_EOFACK;
  1427.             break;
  1428.  
  1429.             /*---------------------------------------------------------*/
  1430.         case HTX_END:
  1431.             txpkt (0, HPKT_END);
  1432.             txpkt (0, HPKT_END);
  1433.             txtimer = h_timer_set (timeout / 2);
  1434.             txstate = HTX_ENDACK;
  1435.             break;
  1436.  
  1437.             /*---------------------------------------------------------*/
  1438.         default:
  1439.             break;
  1440.  
  1441.             /*---------------------------------------------------------*/
  1442.         }
  1443.  
  1444.         /*----------------------------------------------------------------*/
  1445.         pkttype = rxpkt ();
  1446.  
  1447.         /*----------------------------------------------------------*/
  1448.         switch (pkttype)
  1449.         {
  1450.             /*---------------------------------------------------*/
  1451.         case H_CARRIER:
  1452.         case H_CANCEL:
  1453.         case H_SYSABORT:
  1454.         case H_BRAINTIME:
  1455.             switch (pkttype)
  1456.             {
  1457.             case H_CARRIER:
  1458.                 j_status (GenericError, &(MSG_TXT (M_NO_CARRIER)[1]));
  1459.                 break;
  1460.             case H_CANCEL:
  1461.                 j_status (MSG_TXT (M_SESSION_ABORT));
  1462.                 break;
  1463.             case H_SYSABORT:
  1464.                 j_status (GenericError, &(MSG_TXT (M_KBD_MSG)[1]));
  1465.                 break;
  1466.             case H_BRAINTIME:
  1467.                 j_status (MSG_TXT (M_OTHER_DIED));
  1468.                 break;
  1469.             }
  1470.             txstate = HTX_DONE;
  1471.             res = XFER_ABORT;
  1472.             break;
  1473.  
  1474.             /*---------------------------------------------------*/
  1475.         case H_TXTIME:
  1476.             if (txstate == HTX_XWAIT || txstate == HTX_REND)
  1477.             {
  1478.                 txpkt (0, HPKT_IDLE);
  1479.                 txtimer = h_timer_set (H_IDLE);
  1480.                 break;
  1481.             }
  1482.  
  1483.             if (++txretries > H_RETRIES)
  1484.             {
  1485.                 j_status (MSG_TXT (M_FUBAR_MSG));
  1486.                 txstate = HTX_DONE;
  1487.                 res = XFER_ABORT;
  1488.                 break;
  1489.             }
  1490.  
  1491.             j_message (Tx_y, MSG_TXT (M_TIMEOUT));
  1492. #ifdef DEBUG
  1493.             j_status ("-HSEND: Timeout - Retry %u", txretries);
  1494. #endif
  1495.             txtimer = h_timer_reset ();
  1496.  
  1497.             switch (txstate)
  1498.             {
  1499.             case HTX_SWAIT:
  1500.                 txstate = HTX_START;
  1501.                 break;
  1502.             case HTX_INITACK:
  1503.                 txstate = HTX_INIT;
  1504.                 break;
  1505.             case HTX_FINFOACK:
  1506.                 txstate = HTX_FINFO;
  1507.                 break;
  1508.             case HTX_DATAACK:
  1509.                 txstate = HTX_XDATA;
  1510.                 break;
  1511.             case HTX_EOFACK:
  1512.                 txstate = HTX_EOF;
  1513.                 break;
  1514.             case HTX_ENDACK:
  1515.                 txstate = HTX_END;
  1516.                 break;
  1517.             }
  1518.             break;
  1519.  
  1520.             /*---------------------------------------------------*/
  1521. #ifdef HYDRADEV
  1522.         case H_DEVTXTIME:
  1523.             if (++devtxretries > H_RETRIES)
  1524.             {
  1525.                 j_status (MSG_TXT (M_FUBAR_MSG));
  1526.                 txstate = HTX_DONE;
  1527.                 res = XFER_ABORT;
  1528.                 break;
  1529.             }
  1530.  
  1531.             j_message (Tx_y, MSG_TXT (M_TIMEOUT));
  1532. #ifdef DEBUG
  1533.             j_status ("-HDEVTX: Timeout - Retry %u", devtxretries);
  1534. #endif
  1535.             devtxtimer = h_timer_reset ();
  1536.             devtxstate = HTD_DATA;
  1537.             break;
  1538. #endif
  1539.             /*---------------------------------------------------*/
  1540.         case HPKT_START:
  1541.             if (txstate == HTX_START || txstate == HTX_SWAIT)
  1542.             {
  1543.                 txtimer = h_timer_reset ();
  1544.                 txretries = 0;
  1545.                 txstate = HTX_INIT;
  1546.                 braindead = h_timer_set (H_BRAINDEAD);
  1547.             }
  1548.             break;
  1549.  
  1550.             /*---------------------------------------------------*/
  1551.         case HPKT_INIT:
  1552.             if (rxstate == HRX_INIT)
  1553.             {
  1554.                 p = (char *) rxbuf;
  1555.                 p += ((int) strlen (p)) + 1;
  1556.                 q = p + ((int) strlen (p)) + 1;
  1557.                 rxoptions = options | HUNN_OPTIONS;
  1558.                 rxoptions |= get_flags (q, h_flags);
  1559.                 rxoptions &= get_flags (p, h_flags);
  1560.                 rxoptions &= HCAN_OPTIONS;
  1561.                 if (rxoptions < (options & HNEC_OPTIONS))
  1562.                 {
  1563.                     j_status ("!HYDRA: Incompatible on this link");
  1564.                     txstate = HTX_DONE;
  1565.                     res = XFER_ABORT;
  1566.                     break;
  1567.                 }
  1568.                 p = q + ((int) strlen (q)) + 1;
  1569.                 rxwindow = txwindow = 0L;
  1570.                 sscanf (p, "%08lx%08lx", &rxwindow, &txwindow);
  1571.                 if (rxwindow < 0L)
  1572.                     rxwindow = 0L;
  1573.                 if (hydra_rxwindow &&
  1574.                     (!rxwindow || hydra_rxwindow < rxwindow))
  1575.                     rxwindow = hydra_rxwindow;
  1576.                 if (txwindow < 0L)
  1577.                     txwindow = 0L;
  1578.                 if (hydra_txwindow &&
  1579.                     (!txwindow || hydra_txwindow < txwindow))
  1580.                     txwindow = hydra_txwindow;
  1581.                 p += ((int) strlen (p)) + 1;
  1582.                 strncpy (txpktprefix, p, H_PKTPREFIX);
  1583.                 txpktprefix[H_PKTPREFIX] = '\0';
  1584.  
  1585.                 if (!batchesdone)
  1586.                 {
  1587.                     long revstamp;
  1588.  
  1589.                     p = (char *) rxbuf;
  1590.                     sscanf (p, "%08lx", &revstamp);
  1591.                     j_status (">HYDRA: Other's HydraRev=%s",
  1592.                         h_revdate (revstamp));
  1593.                     p += 8;
  1594.                     if ((q = strchr (p, ',')) != NULL)
  1595.                         *q = ' ';
  1596.                     if ((q = strchr (p, ',')) != NULL)
  1597.                         *q = '/';
  1598.                     j_status (">HYDRA: Other's App.Info '%s'", p);
  1599.                     put_flags ((char *) rxbuf, h_flags, rxoptions);
  1600.                     j_status (">HYDRA: Using link options '%s'", rxbuf);
  1601.                     if (txwindow || rxwindow)
  1602.                         j_status (">HYDRA: Window tx=%ld rx=%ld", txwindow, rxwindow);
  1603.                 }
  1604.  
  1605.                 txoptions = rxoptions;
  1606.                 rxstate = HRX_FINFO;
  1607.  
  1608. #ifdef HYDRADEV
  1609.                 if (rxoptions & HOPT_DEVICE)
  1610.                 {
  1611.                     p = "Remote has no chat facility available\r\n";
  1612.                     hydra_devsend ("CON", (byte *) p, (int) strlen (p));
  1613.                 }
  1614. #endif
  1615.             }
  1616.  
  1617.             txpkt (0, HPKT_INITACK);
  1618.             break;
  1619.  
  1620.             /*---------------------------------------------------*/
  1621.         case HPKT_INITACK:
  1622.             if (txstate == HTX_INIT || txstate == HTX_INITACK)
  1623.             {
  1624.                 braindead = h_timer_set (H_BRAINDEAD);
  1625.                 txtimer = h_timer_reset ();
  1626.                 txretries = 0;
  1627.                 txstate = HTX_RINIT;
  1628.             }
  1629.             break;
  1630.  
  1631.             /*---------------------------------------------------*/
  1632.         case HPKT_FINFO:
  1633.             if (rxstate == HRX_FINFO)
  1634.             {
  1635.                 braindead = h_timer_set (H_BRAINDEAD);
  1636.                 if (!rxbuf[0])
  1637.                 {
  1638.                     j_msgend (Rx_y);
  1639. #ifdef DEBUG
  1640.                     j_status ("*HRECV: End of batch");
  1641. #endif
  1642.                     rxpos = 0L;
  1643.                     rxstate = HRX_DONE;
  1644.                     batchesdone++;
  1645.                 }
  1646.                 else
  1647.                 {
  1648.                     long diskfree;
  1649.  
  1650.                     rxfsize = rxftime = 0L;
  1651.                     rxoldpos = rxoldeta = -1;
  1652.                     rxfname[0] = '\0';
  1653.                     sscanf ((char *) rxbuf, "%08lx%08lx%*08lx%*08lx%*08lx%s",
  1654.                         &rxftime, &rxfsize, rxfname);
  1655.                     strlwr (rxfname);
  1656.  
  1657.                     i = strlen (rxfname) - 1;
  1658.                     if ((i > 2) && (rxfname[i - 2] == 'r') &&
  1659.                         (rxfname[i - 1] == 'e') && (rxfname[i] == 'q'))
  1660.                     {
  1661.                         (void) sprintf (&rxfname[i - 1], "%02x", TaskNumber);
  1662.                     }
  1663.  
  1664.                     if (!xfer_init (rxfname, rxfsize, rxftime))    /* Already have file */
  1665.                     {
  1666.                         j_status (MSG_TXT (M_ALREADY_HAVE), rxpathname);
  1667.                         rxpos = -1L;
  1668.                     }
  1669.                     else
  1670.                     {
  1671.                         diskfree = zfree (rxpathname);
  1672.                         if (rxfsize + 10240L > diskfree)
  1673.                         {
  1674.                             j_status (MSG_TXT (M_OUT_OF_DISK_SPACE));
  1675.                             rxpos = -2L;
  1676.                         }
  1677.                         else
  1678.                         {
  1679.                             if (dexists (rxpathname))    /* Resuming? */
  1680.                             {
  1681.                                 if ((rxfd = open (rxpathname, O_RDWR | O_BINARY, 0)) < 0)
  1682.                                 {
  1683.                                     j_error (MSG_TXT (M_OPEN_MSG), rxpathname);
  1684.                                     rxpos = -2L;
  1685.                                 }
  1686.                             }
  1687.                             else if ((rxfd = open (rxpathname, O_CREAT | O_RDWR | O_BINARY, S_IREAD | S_IWRITE)) < 0)
  1688.                             {
  1689.                                 j_error (MSG_TXT (M_OPEN_MSG), rxpathname);
  1690.                                 rxpos = -2L;
  1691.                             }
  1692.  
  1693.                             if (rxfd >= 0)
  1694.                             {
  1695.                                 p = check_netfile (rxfname);
  1696.                                 j_status ("#%s %s %s", MSG_TXT (M_RECEIVING), (p) ? p : " ", rxfname);
  1697.                                 if (!un_attended || !fullscreen)
  1698.                                     Rx_y = Next_y;
  1699.                                 xfer_summary (MSG_TXT (M_RECV), rxfname, &rxfsize, Rx_y);
  1700.                                 if (lseek (rxfd, 0L, SEEK_END) < 0L)
  1701.                                 {
  1702.                                     (void) j_error (MSG_TXT (M_SEEK_MSG), rxpathname);
  1703.                                     hydra_badxfer ();
  1704.                                     rxpos = -2L;
  1705.                                 }
  1706.                                 else
  1707.                                 {
  1708.                                     diskfree = zfree (rxpathname);    /*AGL:07jul93*/
  1709.                                     rxoffset = rxpos = tell (rxfd);
  1710.                                     if (rxpos < 0L)
  1711.                                     {
  1712.                                         (void) j_error (MSG_TXT (M_SEEK_MSG), rxfname);
  1713.                                         hydra_badxfer ();
  1714.                                         rxpos = -2L;
  1715.                                     }
  1716.                                     else
  1717.                                     {
  1718.                                         if ((rxfsize - rxoffset) + 10240L > diskfree)
  1719.                                         {    /*AGL:07jul93*/
  1720.                                             j_status (MSG_TXT (M_OUT_OF_DISK_SPACE));
  1721.                                             hydra_badxfer ();
  1722.                                             rxpos = -2L;
  1723.                                         }
  1724.                                         else
  1725.                                         {
  1726.                                             rxstart = 0L;
  1727.                                             rxtimer = h_timer_reset ();
  1728.                                             rxretries = 0;
  1729.                                             rxlastsync = 0L;
  1730.                                             rxsyncid = 0L;
  1731.                                             update_status (&rxpos, &rxoldpos, rxfsize - rxpos, &rxoldeta, Rx_y);
  1732.                                             if (rxpos > 0L)
  1733.                                             {
  1734.                                                 j_status (MSG_TXT (M_SYNCHRONIZING_OFFSET), rxpos);
  1735.                                             }
  1736.                                             rxstate = HRX_DATA;
  1737.                                         }
  1738.                                     }
  1739.                                 }
  1740.                             }
  1741.                         }
  1742.                     }
  1743.                 }
  1744.             }
  1745.             else if (rxstate == HRX_DONE)
  1746.                 rxpos = (!rxbuf[0]) ? 0L : -2L;
  1747.  
  1748.             h_long1 (txbufin) = intell (rxpos);
  1749.             txpkt ((int) sizeof (long), HPKT_FINFOACK);
  1750.  
  1751.             break;
  1752.  
  1753.             /*---------------------------------------------------*/
  1754.         case HPKT_FINFOACK:
  1755.             if (txstate == HTX_FINFO || txstate == HTX_FINFOACK)
  1756.             {
  1757.                 braindead = h_timer_set (H_BRAINDEAD);
  1758.                 txretries = 0;
  1759.                 if (!txfname[0])
  1760.                 {
  1761.                     txtimer = h_timer_set (H_IDLE);
  1762.                     txstate = HTX_REND;
  1763.                 }
  1764.                 else
  1765.                 {
  1766.                     txtimer = h_timer_reset ();
  1767.                     txpos = intell (h_long1 (rxbuf));
  1768.                     if (txpos >= 0L)
  1769.                     {
  1770.                         txoffset = txpos;
  1771.                         txlastack = txpos;
  1772.                         update_status (&txpos, &txoldpos, txfsize - txpos, &txoldeta, Tx_y);
  1773.                         if (txpos > 0L)
  1774.                         {
  1775.                             j_status (MSG_TXT (M_SYNCHRONIZING_OFFSET), txpos);
  1776.                             if (lseek (txfd, txpos, SEEK_SET) < 0L)
  1777.                             {
  1778.                                 (void) j_error (MSG_TXT (M_SEEK_MSG), txfname);
  1779.                                 close (txfd);
  1780.                                 txfd = -1;
  1781.                                 txpos = -2L;
  1782.                                 txstate = HTX_EOF;
  1783.                                 break;
  1784.                             }
  1785.                         }
  1786.                         txstate = HTX_XDATA;
  1787.                     }
  1788.                     else
  1789.                     {
  1790.                         close (txfd);
  1791.                         if (txpos == -1L)
  1792.                         {
  1793.                             j_status (MSG_TXT (M_REMOTE_REFUSED), txfname);
  1794.                             return (XFER_OK);
  1795.                         }
  1796.                         else
  1797.                             /* (txpos < -1L) file NOT sent */
  1798.                         {
  1799.                             j_status ("+HSEND: Skipping %s", txfname);
  1800.                             return (XFER_SKIP);
  1801.                         }
  1802.                     }
  1803.                 }
  1804.             }
  1805.             break;
  1806.  
  1807.             /*---------------------------------------------------*/
  1808.         case HPKT_DATA:
  1809.             if (rxstate == HRX_DATA)
  1810.             {
  1811.                 if (intell (h_long1 (rxbuf)) != rxpos ||
  1812.                     intell (h_long1 (rxbuf)) < 0L)
  1813.                 {
  1814.                     if (intell (h_long1 (rxbuf)) <= rxlastsync)
  1815.                     {
  1816.                         rxtimer = h_timer_reset ();
  1817.                         rxretries = 0;
  1818.                     }
  1819.                     rxlastsync = intell (h_long1 (rxbuf));
  1820.  
  1821.                     if (!h_timer_running (rxtimer) ||
  1822.                         h_timer_expired (rxtimer, h_timer_get ()))
  1823.                     {
  1824.                         if (rxretries > 4)
  1825.                         {
  1826.                             if (txstate < HTX_REND &&
  1827.                                 !originator && !hdxlink)
  1828.                             {
  1829.                                 hdxlink = TRUE;
  1830.                                 rxretries = 0;
  1831.                             }
  1832.                         }
  1833.                         if (++rxretries > H_RETRIES)
  1834.                         {
  1835.                             j_status (MSG_TXT (M_FUBAR_MSG));
  1836.                             txstate = HTX_DONE;
  1837.                             res = XFER_ABORT;
  1838.                             break;
  1839.                         }
  1840.                         if (rxretries == 1 || rxretries == 4)    /*AGL:14may93*/
  1841.                             rxsyncid++;
  1842.  
  1843.                         rxblklen /= 2;
  1844.                         i = rxblklen;
  1845.                         if (i <= 64)
  1846.                             i = 64;
  1847.                         else if (i <= 128)
  1848.                             i = 128;
  1849.                         else if (i <= 256)
  1850.                             i = 256;
  1851.                         else if (i <= 512)
  1852.                             i = 512;
  1853.                         else
  1854.                             i = 1024;
  1855.                         j_message (Rx_y, MSG_TXT (M_J_BAD_PACKET), rxpos);
  1856. #ifdef DEBUG
  1857.                         j_status ("-HRECV: Bad pkt at %ld - Retry %u (newblklen=%u)",
  1858.                                 rxpos, rxretries, i);
  1859. #endif
  1860.                         h_long1 (txbufin) = intell (rxpos);
  1861.                         h_long2 (txbufin) = intell ((long) i);
  1862.                         h_long3 (txbufin) = intell (rxsyncid);
  1863.                         txpkt (3 * ((int) sizeof (long)), HPKT_RPOS);
  1864.  
  1865.                         rxtimer = h_timer_set (timeout);
  1866.                     }
  1867.                 }
  1868.                 else
  1869.                 {
  1870.                     braindead = h_timer_set (H_BRAINDEAD);
  1871.                     rxpktlen -= (int) sizeof (long);
  1872.  
  1873.                     rxblklen = rxpktlen;
  1874.                     if (write (rxfd, rxbuf + ((int) sizeof (long)), rxpktlen) < 0)
  1875.                     {
  1876.                         j_error (MSG_TXT (M_WRITE_MSG), rxfname);
  1877.                         hydra_badxfer ();
  1878.                         rxpos = -2L;
  1879.                         rxretries = 1;
  1880.                         rxsyncid++;
  1881.                         h_long1 (txbufin) = intell (rxpos);
  1882.                         h_long2 (txbufin) = intell (0L);
  1883.                         h_long3 (txbufin) = intell (rxsyncid);
  1884.                         txpkt (3 * ((int) sizeof (long)), HPKT_RPOS);
  1885.  
  1886.                         rxtimer = h_timer_set (timeout);
  1887.                         break;
  1888.                     }
  1889.                     rxretries = 0;
  1890.                     rxtimer = h_timer_reset ();
  1891.                     rxlastsync = rxpos;
  1892.                     rxpos += rxpktlen;
  1893.                     if (rxwindow)
  1894.                     {
  1895.                         h_long1 (txbufin) = intell (rxpos);
  1896.                         txpkt ((int) sizeof (long), HPKT_DATAACK);
  1897.                     }
  1898.                     if (!rxstart)
  1899.                         rxstart = time (NULL) -
  1900.                             ((rxpktlen * 10) / cur_baud.rate_value);
  1901.                     update_status (&rxpos, &rxoldpos, rxfsize - rxpos, &rxoldeta, Rx_y);
  1902.                 }                /*badpkt*/
  1903.             }                    /*rxstate==HRX_DATA*/
  1904.             break;
  1905.  
  1906.             /*---------------------------------------------------*/
  1907.         case HPKT_DATAACK:
  1908.             if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1909.                 txstate == HTX_XWAIT ||
  1910.                 txstate == HTX_EOF || txstate == HTX_EOFACK)
  1911.             {
  1912.                 if (txwindow && intell (h_long1 (rxbuf)) > txlastack)
  1913.                 {
  1914.                     txlastack = intell (h_long1 (rxbuf));
  1915.                     if (txstate == HTX_DATAACK &&
  1916.                         (txpos < (txlastack + txwindow)))
  1917.                     {
  1918.                         txstate = HTX_XDATA;
  1919.                         txretries = 0;
  1920.                         txtimer = h_timer_reset ();
  1921.                     }
  1922.                 }
  1923.             }
  1924.             break;
  1925.  
  1926.             /*---------------------------------------------------*/
  1927.         case HPKT_RPOS:
  1928.             if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1929.                 txstate == HTX_XWAIT ||
  1930.                 txstate == HTX_EOF || txstate == HTX_EOFACK)
  1931.             {
  1932.                 if (intell (h_long3 (rxbuf)) != txsyncid)
  1933.                 {
  1934.                     txsyncid = intell (h_long3 (rxbuf));
  1935.                     txretries = 1;
  1936.                 }
  1937.                 else
  1938.                     /*AGL:14may93*/
  1939.                 {
  1940.                     if (++txretries > H_RETRIES)
  1941.                     {
  1942.                         j_status (MSG_TXT (M_FUBAR_MSG));
  1943.                         txstate = HTX_DONE;
  1944.                         res = XFER_ABORT;
  1945.                         break;
  1946.                     }
  1947.                     if (txretries != 4)
  1948.                         break;    /*AGL:14may93*/
  1949.                 }
  1950.  
  1951.                 txtimer = h_timer_reset ();
  1952.                 txpos = intell (h_long1 (rxbuf));
  1953.                 if (txpos < 0L)
  1954.                 {
  1955.                     if (txfd >= 0)
  1956.                     {
  1957.                         j_status ("+HSEND: Skipping %s", txfname);
  1958.                         close (txfd);
  1959.                         txfd = -1;
  1960.                         txstate = HTX_EOF;
  1961.                     }
  1962.                     txpos = -2L;
  1963.                     break;
  1964.                 }
  1965.  
  1966.                 if (txblklen > (word) intell (h_long2 (rxbuf)))
  1967.                     txblklen = (word) intell (h_long2 (rxbuf));
  1968.                 else
  1969.                     txblklen >>= 1;
  1970.                 if (txblklen <= 64)
  1971.                     txblklen = 64;
  1972.                 else if (txblklen <= 128)
  1973.                     txblklen = 128;
  1974.                 else if (txblklen <= 256)
  1975.                     txblklen = 256;
  1976.                 else if (txblklen <= 512)
  1977.                     txblklen = 512;
  1978.                 else
  1979.                     txblklen = 1024;
  1980.                 txgoodbytes = 0;
  1981.                 txgoodneeded += txmaxblklen * 2;    /*AGL:23feb93*/
  1982.                 if (txgoodneeded > txmaxblklen * 8)    /*AGL:23feb93*/
  1983.                     txgoodneeded = txmaxblklen * 8;    /*AGL:23feb93*/
  1984.  
  1985.                 update_status (&txpos, &txoldpos, txfsize - txpos, &txoldeta, Tx_y);
  1986.                 j_status (MSG_TXT (M_SYNCHRONIZING_OFFSET), txpos);
  1987.                 if (lseek (txfd, txpos, SEEK_SET) < 0L)
  1988.                 {
  1989.                     (void) j_error (MSG_TXT (M_SEEK_MSG), txfname);
  1990.                     close (txfd);
  1991.                     txfd = -1;
  1992.                     txpos = -2L;
  1993.                     txstate = HTX_EOF;
  1994.                     break;
  1995.                 }
  1996.  
  1997.                 if (txstate != HTX_XWAIT)
  1998.                     txstate = HTX_XDATA;
  1999.             }
  2000.             break;
  2001.  
  2002.             /*---------------------------------------------------*/
  2003.         case HPKT_EOF:
  2004.             if (rxstate == HRX_DATA)
  2005.             {
  2006.                 if (intell (h_long1 (rxbuf)) < 0L)
  2007.                 {
  2008.                     hydra_badxfer ();
  2009.                     j_status ("+HRECV: Skipping %s", rxfname);
  2010.                     rxstate = HRX_FINFO;
  2011.                     braindead = h_timer_set (H_BRAINDEAD);
  2012.                 }
  2013.                 else if (intell (h_long1 (rxbuf)) != rxpos)
  2014.                 {
  2015.                     if (intell (h_long1 (rxbuf)) <= rxlastsync)
  2016.                     {
  2017.                         rxtimer = h_timer_reset ();
  2018.                         rxretries = 0;
  2019.                     }
  2020.                     rxlastsync = intell (h_long1 (rxbuf));
  2021.  
  2022.                     if (!h_timer_running (rxtimer) ||
  2023.                         h_timer_expired (rxtimer, h_timer_get ()))
  2024.                     {
  2025.                         if (++rxretries > H_RETRIES)
  2026.                         {
  2027.                             j_status (MSG_TXT (M_FUBAR_MSG));
  2028.                             txstate = HTX_DONE;
  2029.                             res = XFER_ABORT;
  2030.                             break;
  2031.                         }
  2032.                         if (rxretries == 1 || rxretries == 4)    /*AGL:14may93*/
  2033.                             rxsyncid++;
  2034.  
  2035.                         rxblklen /= 2;
  2036.                         i = rxblklen;
  2037.                         if (i <= 64)
  2038.                             i = 64;
  2039.                         else if (i <= 128)
  2040.                             i = 128;
  2041.                         else if (i <= 256)
  2042.                             i = 256;
  2043.                         else if (i <= 512)
  2044.                             i = 512;
  2045.                         else
  2046.                             i = 1024;
  2047.  
  2048.                         j_status ("-HRECV: Bad EOF at %ld - Retry %u (newblklen=%u)",
  2049.                             rxpos, rxretries, i);
  2050.                         h_long1 (txbufin) = intell (rxpos);
  2051.                         h_long2 (txbufin) = intell ((long) i);
  2052.                         h_long3 (txbufin) = intell (rxsyncid);
  2053.                         txpkt (3 * ((int) sizeof (long)), HPKT_RPOS);
  2054.  
  2055.                         rxtimer = h_timer_set (timeout);
  2056.                     }
  2057.                 }
  2058.                 else
  2059.                 {
  2060.                     long rxtime;
  2061.  
  2062.                     close (rxfd);
  2063.                     rxfd = -1;
  2064.  
  2065.                     if (Resume_WaZOO)    /* resumed transfer? */
  2066.                     {
  2067.                         if (xfer_okay ())
  2068.                         {
  2069.                             j_status (MSG_TXT (M_RENAME_MSG), rxpathname);
  2070.                         }
  2071.                     }
  2072.  
  2073.                     if (rxftime > 0) /* utime doesn't like negative numbers */
  2074.                     {
  2075.                         struct utimbuf utimes;
  2076.  
  2077.                         utimes.UT_ACTIME = rxftime;
  2078.                         utimes.modtime = rxftime;
  2079.                         (void) utime (rxpathname, (UTIMBUF *) & utimes);
  2080.                     }
  2081.  
  2082.                     rxtime = through (&rxfsize, &rxstart);
  2083.                     rxfsize = rxpos - rxoffset;
  2084.                     j_status ("%s-H%s %s", MSG_TXT (M_FILE_RECEIVED), (txoptions & HOPT_CRC32) ? "/32" : " ", rxpathname);
  2085.                     j_msgend (Rx_y);
  2086.                     update_files (0, rxpathname, rxfsize, rxtime, 0);
  2087.  
  2088.                     rxstate = HRX_FINFO;
  2089.                     braindead = h_timer_set (H_BRAINDEAD);
  2090.                 }                /*skip/badeof/eof*/
  2091.             }                    /*rxstate==HRX_DATA*/
  2092.  
  2093.             if (rxstate == HRX_FINFO)
  2094.                 txpkt (0, HPKT_EOFACK);
  2095.             break;
  2096.  
  2097.             /*---------------------------------------------------*/
  2098.         case HPKT_EOFACK:
  2099.             if (txstate == HTX_EOF || txstate == HTX_EOFACK)
  2100.             {
  2101.                 braindead = h_timer_set (H_BRAINDEAD);
  2102.                 if (txfd >= 0)
  2103.                 {
  2104.                     long txtime;
  2105.  
  2106.                     close (txfd);
  2107.  
  2108.                     txfsize = txpos - txoffset;
  2109.                     txtime = through (&txfsize, &txstart);
  2110.                     j_status ("%s-H%s %s", MSG_TXT (M_FILE_SENT), (txoptions & HOPT_CRC32) ? "/32" : " ", txpathname);
  2111.                     j_msgend (Tx_y);
  2112.                     update_files (1, txpathname, txfsize, txtime, 0);
  2113.  
  2114.                     return (XFER_OK);
  2115.                 }
  2116.                 else
  2117.                     return (XFER_SKIP);
  2118.             }
  2119.             break;
  2120.  
  2121.             /*---------------------------------------------------*/
  2122.         case HPKT_IDLE:
  2123.             if (txstate == HTX_XWAIT)
  2124.             {
  2125.                 hdxlink = FALSE;
  2126.                 txtimer = h_timer_reset ();
  2127.                 txretries = 0;
  2128.                 txstate = HTX_XDATA;
  2129.             }
  2130.             else if (txstate >= HTX_FINFO && txstate < HTX_REND)
  2131.                 braindead = h_timer_set (H_BRAINDEAD);
  2132.             break;
  2133.  
  2134.             /*---------------------------------------------------*/
  2135.         case HPKT_END:
  2136.             if (txstate == HTX_END || txstate == HTX_ENDACK)
  2137.             {
  2138.                 txpkt (0, HPKT_END);
  2139.                 txpkt (0, HPKT_END);
  2140.                 txpkt (0, HPKT_END);
  2141. #ifdef DEBUG
  2142.                 j_status ("+HYDRA: Completed");
  2143. #endif
  2144.                 txstate = HTX_DONE;
  2145.                 res = XFER_OK;
  2146.             }
  2147.             break;
  2148.  
  2149. #ifdef HYDRADEV
  2150.             /*---------------------------------------------------*/
  2151.         case HPKT_DEVDATA:
  2152.             if (devrxid != intell (h_long1 (rxbuf)))
  2153.             {
  2154.                 hydra_devrecv ();
  2155.                 devrxid = intell (h_long1 (rxbuf));
  2156.             }
  2157.             h_long1 (txbufin) = h_long1 (rxbuf);    /*AGL:10feb93*/
  2158.             txpkt ((int) sizeof (long), HPKT_DEVDACK);
  2159.  
  2160.             break;
  2161.  
  2162.             /*---------------------------------------------------*/
  2163.         case HPKT_DEVDACK:
  2164.             if (devtxstate && (devtxid == intell (h_long1 (rxbuf))))
  2165.             {
  2166.                 devtxtimer = h_timer_reset ();
  2167.                 devtxstate = HTD_DONE;
  2168.             }
  2169.             break;
  2170. #endif
  2171.  
  2172.             /*---------------------------------------------------*/
  2173.         default:                /* unknown packet types: IGNORE, no error! */
  2174.             break;
  2175.  
  2176.             /*---------------------------------------------------*/
  2177.         }                        /*(pkttype)*/
  2178.  
  2179.         /*------------------------------------------------------*/
  2180.         switch (txstate)
  2181.         {
  2182.             /*---------------------------------------------------*/
  2183.         case HTX_START:
  2184.         case HTX_SWAIT:
  2185.             if (rxstate == HRX_FINFO)
  2186.             {
  2187.                 txtimer = h_timer_reset ();
  2188.                 txretries = 0;
  2189.                 txstate = HTX_INIT;
  2190.             }
  2191.             break;
  2192.  
  2193.             /*---------------------------------------------------*/
  2194.         case HTX_RINIT:
  2195.             if (rxstate == HRX_FINFO)
  2196.             {
  2197.                 txtimer = h_timer_reset ();
  2198.                 txretries = 0;
  2199.                 txstate = HTX_FINFO;
  2200.             }
  2201.             break;
  2202.  
  2203.             /*---------------------------------------------------*/
  2204.         case HTX_XDATA:
  2205.             if (rxstate && hdxlink)
  2206.             {
  2207.                 j_status (MSG_TXT (M_GOING_ONE_WAY));
  2208. #ifdef HYDRADEV
  2209.                 hydra_devsend ("MSG", (byte *) hdxmsg, (int) strlen (hdxmsg));
  2210. #endif
  2211.                 txtimer = h_timer_set (H_IDLE);
  2212.                 txstate = HTX_XWAIT;
  2213.             }
  2214.             break;
  2215.  
  2216.             /*---------------------------------------------------*/
  2217.         case HTX_XWAIT:
  2218.             if (!rxstate)
  2219.             {
  2220.                 txtimer = h_timer_reset ();
  2221.                 txretries = 0;
  2222.                 txstate = HTX_XDATA;
  2223.             }
  2224.             break;
  2225.  
  2226.             /*---------------------------------------------------*/
  2227.         case HTX_REND:
  2228. #ifdef HYDRADEV
  2229.             if (!rxstate && !devtxstate)
  2230. #else
  2231.             if (!rxstate)
  2232. #endif
  2233.             {
  2234.                 txtimer = h_timer_reset ();
  2235.                 txretries = 0;
  2236.                 txstate = HTX_END;
  2237.             }
  2238.             break;
  2239.  
  2240.             /*---------------------------------------------------*/
  2241.         default:                /* any other state - nothing to do */
  2242.             break;
  2243.  
  2244.         }                        /*switch(txstate)*/
  2245.  
  2246.     }
  2247.     while (txstate);
  2248.  
  2249.     if (txfd >= 0)
  2250.         close (txfd);
  2251.     hydra_badxfer ();
  2252.  
  2253.     if (res == XFER_ABORT)
  2254.     {
  2255.         CLEAR_OUTBOUND ();
  2256.         if (remote_capabilities)
  2257.             LOWER_DTR ();
  2258.         if (CARRIER)
  2259.         {
  2260.             braindead = h_timer_set (10);    /* wait max. 10s after abort */
  2261.             ComTXBlockTimeout (abortstr, (int) strlen (abortstr), braindead);
  2262.             while (!OUT_EMPTY () && CARRIER && !h_timer_expired (braindead, h_timer_get ()))
  2263.                 time_release ();
  2264.             CLEAR_OUTBOUND ();
  2265.         }
  2266.         CLEAR_INBOUND ();
  2267.         mail_finished = 0;
  2268.     }
  2269.     else
  2270.     {
  2271.         braindead = h_timer_set (10);    /* wait max. 10s after abort */
  2272.         while (!OUT_EMPTY () && CARRIER && !h_timer_expired (braindead, h_timer_get ()))
  2273.             time_release ();
  2274.     }
  2275.     return (res);
  2276. }                                /*hydra()*/
  2277.  
  2278. /* end of hydra.c */
  2279.