FTSC.C

24.1 KB 0dc9bf97241e5ea9…
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*  (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/*                                                                          */
/*                                                                          */
/*                 This module was written by Bob Hartman                   */
/*                                                                          */
/*                                                                          */
/*                 BinkleyTerm FTSC Mail Session Routines                   */
/*                                                                          */
/*                                                                          */
/*    For complete  details  of the licensing restrictions, please refer    */
/*    to the License  agreement,  which  is published in its entirety in    */
/*    the MAKEFILE and BT.C, and also contained in the file LICENSE.250.    */
/*                                                                          */
/*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
/*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
/*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
/*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
/*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
/*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
/*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
/*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
/*                                                                          */
/*                                                                          */
/* You can contact Bit Bucket Software Co. at any one of the following      */
/* addresses:                                                               */
/*                                                                          */
/* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
/* P.O. Box 460398                AlterNet 7:491/0                          */
/* Aurora, CO 80046               BBS-Net  86:2030/1                        */
/*                                Internet f491.n343.z1.fidonet.org         */
/*                                                                          */
/* Please feel free to contact us at any time to share your comments about  */
/* our software and/or licensing policies.                                  */
/*                                                                          */
/*--------------------------------------------------------------------------*/

/* Include this file before any other includes or defines! */

#include "includes.h"

#define rb_plus "r+b"

int FTSC_callback (char *);
int FTSC_time (long);
int FTSC_sendmail (void);
int FTSC_recvmail (int);

#define NUM_FLAGS 4

void FTSC_sender (int wz)
{
   int j;
   char junkbuff[128];
   long t1;

   XON_DISABLE ();
   first_block = 0;

   if (!wz)
      {
      first_block = 1;
      status_line (MSG_TXT(M_SEND_FALLBACK));
      who_is_he = 0;
      (void) sprintf (junkbuff, "*%s (%s)",
                         newnodedes.SystemName,
                            Full_Addr_Str (&remote_addr));
      status_line (junkbuff);
      }

   Netmail_Session = 1;

   (void) FTSC_sendmail ();
   t1 = timerset (4500);

   /* See what the receiver would like us to do */
   while ((!timeup (t1)) && CARRIER)
      {
      if ((j = PEEKBYTE ()) >= 0)
         {
         switch (j)
            {
            case TSYNC:
               CLEAR_INBOUND ();
               if (FTSC_recvmail (1))
                  goto get_out;
               t1 = timerset (4500);
               break;

            case SYN:
               CLEAR_INBOUND ();
               if (on_our_nickel)
                  (void) SEA_recvreq ();
               else
                  {
                  SENDBYTE (CAN);
                  status_line (MSG_TXT(M_REFUSING_IN_FREQ));
                  }
               t1 = timerset (4500);
               break;

            case ENQ:
               CLEAR_INBOUND ();
               SEA_sendreq ();
               goto get_out;

            case NAK:
            case 'C':
               CLEAR_INBOUND ();
               SENDBYTE (EOT);
               t1 = timerset (4500);
               break;

            default:
               CLEAR_INBOUND ();
               SENDBYTE (SUB);
               break;
            }
         }
      else
         {
         time_release ();
         }
      }

   if (!CARRIER)
      {
      status_line (MSG_TXT(M_NO_CARRIER));
      CLEAR_INBOUND ();
      first_block = 0;
      return;
      }

   if (timeup (t1))
      {
      (void) FTSC_recvmail (1);
      status_line (MSG_TXT(M_TOO_LONG));
      }

get_out:
   first_block = 0;
   t1 = timerset (100);
   while (!timeup (t1))
      time_release ();
   if (!wz)
      status_line (MSG_TXT(M_0001_END));
}

int FTSC_receiver (int wz)
{
   char fname[64];
   int havemail, done, np;
   unsigned int i;
   long t1, t2;
   struct stat buf;
   char *HoldName;
   struct FILEINFO dta;
   ADDR tmp;

   first_block = 0;
   XON_DISABLE ();

   if (!wz)
      {
     first_block = 1;
      status_line (MSG_TXT(M_RECV_FALLBACK));
      who_is_he = 1;
      }

   Netmail_Session = 1;

   CLEAR_INBOUND ();

   /* Save the state of pickup for now */
   done = no_pickup;
   no_pickup = 0;
   if (FTSC_recvmail (0))
      {
      /* Restore the state of pickup */
      no_pickup = done;
      if (!wz)
         status_line (MSG_TXT(M_0001_END));
      first_block = 0;
      return (1);
      }

   /* Restore the state of pickup */
   no_pickup = done;

   remote_addr = called_addr;

   HoldName = HoldAreaNameMunge(&called_addr);

   /* Now see if we should send anything back to him */
   (void) sprintf (fname, "%s%s.?UT", HoldName, Hex_Addr_Str (&remote_addr));
   havemail = !dfind (&dta, fname, 0);

   if (!havemail)
      {
      (void) sprintf (fname, "%s%s.?LO", HoldName, Hex_Addr_Str (&remote_addr));
      havemail = !dfind (&dta, fname, 0);
      }

   if (!havemail)
      {
      for (np = 0; np <= ALIAS_CNT; np++)
         {
         if (alias[np].Net == 0)
            break;
         (void) sprintf (fname, "%s%s.REQ", CURRENT.sc_Inbound, Hex_Addr_Str (&(alias[np])));
         havemail = !dfind (&dta, fname, 0);
         if (havemail)
            break;
         }
      }

   if (!havemail)
      {
      status_line (MSG_TXT(M_NOTHING_TO_SEND), Full_Addr_Str (&remote_addr));
      }
   else
      {
      /* OS/2 likes this */
      while (!dfind (&dta, NULL, 1))
         ;
      status_line (MSG_TXT(M_GIVING_MAIL), Full_Addr_Str (&remote_addr));
      /* Send the TSYNC's until we get a C or NAK or CAN back */
      t1 = timerset (3000);                      /* set 30 second timeout */
      done = 0;
      while (!timeup (t1) && CARRIER && !done)   /* till then or CD lost  */
         {
         SENDBYTE (TSYNC);

         t2 = timerset (300);
         while (CARRIER && (!timeup (t2)) && !done)
            {
            switch (TIMED_READ (0))
               {
               case 'C':
               case NAK:
                  done = 1;
                  (void) FTSC_sendmail ();
                  break;

               case CAN:
                  done = 1;
                  status_line (MSG_TXT(M_REFUSE_PICKUP), Full_Addr_Str (&remote_addr));
                  break;

               default:
                  time_release ();
               }
            }
         }
      }

   first_block = 0;

   if (wz)
      return TRUE;                      /* All done if this is WaZOO */

   /* Now see if we want to request anything */
   tmp = remote_addr;

   /* For a point, massage the address to get the right .REQ filename */

   if (tmp.Point != 0)
      {
      tmp.Node  = tmp.Point;
      tmp.Point = 0;
      tmp.Net   = (pvtnet > 0) ? (unsigned int) pvtnet : 0;
      }        

   (void) sprintf (fname, "%s%s.REQ", HoldName, Hex_Addr_Str (&tmp));
   if (!stat (fname, &buf))
      {
      /* Send the SYN character and wait for an ENQ or CAN */
      t1 = timerset (3000);                      /* set 30 second timeout */
      done = 0;
      while (!timeup (t1) && CARRIER && !done)   /* till then or CD lost  */
         {
         SENDBYTE (SYN);

         t2 = timerset (500);
         while (CARRIER && (!timeup (t2)) && !done)
            {
            i = (unsigned) TIMED_READ (0);

            switch (i)
               {
               case ENQ:
                  SEA_sendreq ();
                  break;

               case CAN:
                  done = 1;
                  break;

               case 'C':
               case NAK:
                  SENDBYTE (EOT);
                  break;

               case SUB:
                  SENDBYTE (SYN);
                  break;

               default:
                  time_release ();
               }
            }
         }
      }

   /* Finally, can he request anything from us */
   if (!no_requests)
      (void) SEA_recvreq ();

   status_line (MSG_TXT(M_0001_END));
   return TRUE;
}

int FTSC_sendmail ()
{
   FILE *fp;
   char fname[80];
   char s[80];
   char *sptr;
   char *HoldName;
   int c;
   int i;
   int j = 0;
   struct stat buf;
   struct _pkthdr *tmppkt;
   time_t t1;
   struct tm *tm1;

   XON_DISABLE ();

   sptr = s;
   /*--------------------------------------------------------------------*/
   /* Send all waiting ?UT files (mail packets)                          */
   /*--------------------------------------------------------------------*/
   *ext_flags = 'O';
   HoldName = HoldAreaNameMunge(&called_addr);
   for (c = 0; c < NUM_FLAGS; c++)
      {
#ifndef JACK_DECKER
      if (caller && (ext_flags[c] == 'H'))
         continue;
#endif

      (void) sprintf (fname,
               "%s%s.%cUT",
               HoldName, Hex_Addr_Str (&called_addr), ext_flags[c]);

      if (!stat (fname, &buf))
         break;
      }                                          /* for */

   /*--- Build a dummy PKT file name */
   invent_pkt_name (s);

   status_line (MSG_TXT(M_PACKET_MSG));

   if (c == NUM_FLAGS)
      {
      (void) sprintf (fname,
               "%s%s.OUT",
               HoldName, Hex_Addr_Str (&called_addr));
      if ((fp = fopen (fname, "wb")) == NULL)
         {
         (void) got_error (MSG_TXT(M_OPEN_MSG), fname);
         return (1);
         }
      t1 = time (NULL);
      tm1 = localtime (&t1);

      tmppkt = (struct _pkthdr *) calloc (1, sizeof (struct _pkthdr));
      if (tmppkt == NULL)
         {
         status_line (MSG_TXT(M_MEM_ERROR));
         (void) fclose (fp);
         return (1);
         }
      tmppkt->orig_node = (int) alias[assumed].Node;
      tmppkt->dest_node = called_addr.Node;
      tmppkt->ver = PKTVER;
      tmppkt->orig_net = (int) alias[assumed].Net;
      tmppkt->dest_net = called_addr.Net;
      tmppkt->product = PRDCT_CODE;
      if (n_getpassword (&called_addr))
         {
         if (remote_password != NULL)
            {
            (void) strupr (remote_password);
            (void) strncpy ((char *) (tmppkt->password), remote_password, 8);
            }
         }
      tmppkt->orig_zone = (int) alias[assumed].Zone;
      tmppkt->dest_zone = called_addr.Zone;

      if (((called_addr.Domain != NULL)
      &&  (called_addr.Domain != alias[assumed].Domain)
      &&  (my_addr.Domain != NULL))
      ||  (alias[assumed].Point != 0))
         {
         /* Make it a type 2.2 packet instead */
         tmppkt->year = alias[assumed].Point;
         tmppkt->month = called_addr.Point;
         tmppkt->day = 0;
         tmppkt->hour = 0;
         tmppkt->minute = 0;
         tmppkt->second = 0;
         tmppkt->rate = 2;
         if (alias[assumed].Domain != NULL)
            {
            for (i = 0; domain_name[i] != NULL; i++)
               {
               if (domain_name[i] == alias[assumed].Domain)
                  {
                  break;
                  }
               }
            if (i < 49)
               {
               (void) strncpy ((char *)tmppkt->B_fill2, domain_abbrev[i], 8);
               }
            }

         for (i = 0; domain_name[i] != NULL; i++)
            {
          if (domain_name[i] == called_addr.Domain)
             {
             break;
               }
            }
         if ((i < 49) && (domain_name[i] != NULL))
          {
          (void) strncpy ((char *)&(tmppkt->B_fill2[8]), domain_abbrev[i], 8);
            }
         }
      else
         {
         tmppkt->year = tm1->tm_year;
         tmppkt->month = tm1->tm_mon;
         tmppkt->day = tm1->tm_mday;
         tmppkt->hour = tm1->tm_hour;
         tmppkt->minute = tm1->tm_min;
         tmppkt->second = tm1->tm_sec;
         tmppkt->rate = 0;
         }

      (void) fwrite ((char *) tmppkt, sizeof (struct _pkthdr), 1, fp);
      free (tmppkt);
      (void) fwrite ("\0\0", 2, 1, fp);
      (void) fclose (fp);
      }
   else
      {
      if ((fp = fopen (fname, rb_plus)) == NULL)
         {
         (void) got_error (MSG_TXT(M_OPEN_MSG), fname);
         return (1);
         }
      tmppkt = (struct _pkthdr *) calloc (1, sizeof (struct _pkthdr));
      if (tmppkt == NULL)
         {
         status_line (MSG_TXT(M_MEM_ERROR));
         return (1);
         }
      if (fread (tmppkt, 1, sizeof (struct _pkthdr), fp) < sizeof (struct _pkthdr))
         {
         (void) got_error (MSG_TXT(M_READ_MSG), fname);
         free (tmppkt);
         (void) fclose (fp);
         return (1);
         }

      if (n_getpassword (&called_addr))
         {
         if (remote_password != NULL)
            {
            (void) strupr (remote_password);
            (void) strncpy ((char *) (tmppkt->password), remote_password, 8);
            }
         }


      /* Make sure the zone info is in there */

      tmppkt->orig_node = (int) alias[assumed].Node;
      tmppkt->orig_net  = (int) alias[assumed].Net;
      tmppkt->orig_zone = (int) alias[assumed].Zone;
      tmppkt->dest_zone = called_addr.Zone;

      if ((called_addr.Domain != NULL) &&
          (called_addr.Domain != alias[assumed].Domain) &&
          (my_addr.Domain != NULL))
         {
         /* Make it a type 2.2 packet instead */
         tmppkt->year = alias[assumed].Point;
         tmppkt->month = called_addr.Point;
         tmppkt->day = 0;
         tmppkt->hour = 0;
         tmppkt->minute = 0;
         tmppkt->second = 0;
         tmppkt->rate = 2;
         if (alias[assumed].Domain != NULL)
            {
            for (i = 0; domain_name[i] != NULL; i++)
               {
               if (domain_name[i] == alias[assumed].Domain)
                  {
                  break;
                  }
               }
            if (i < 49)
               {
         (void) strncpy ((char *)tmppkt->B_fill2, domain_abbrev[i], 8);
         }
      }
   for (i = 0; domain_name[i] != NULL; i++)
      {
      if (domain_name[i] == called_addr.Domain)
         {
         break;
         }
      }
   if (i < 49)
      {
      (void) strncpy ((char *)&(tmppkt->B_fill2[8]), domain_abbrev[i], 8);
            }
         }

      (void) fseek (fp, 0L, SEEK_SET);
      (void) fwrite (tmppkt, 1, sizeof (struct _pkthdr), fp);
      (void) fclose (fp);
      free (tmppkt);
      }

   net_problems = (no_sealink) ? Telink_Send_File (fname, s) : SEAlink_Send_File (fname, s);

   if (net_problems != 0)
      {
      if (c == NUM_FLAGS)
         (void) unlink (fname);
      return (net_problems);
      }

   /* Delete the sent packet */
   (void) unlink (fname);


   /*--------------------------------------------------------------------*/
   /* Send files listed in ?LO files (attached files)                    */
   /*--------------------------------------------------------------------*/
   *ext_flags = 'F';
   status_line (" %s %s", MSG_TXT(M_OUTBOUND), MSG_TXT(M_FILE_ATTACHES));

   if (!do_FLOfile (ext_flags, FTSC_callback))
      return FALSE;


   /*--------------------------------------------------------------------*/
   /* Send our File requests to other system if it's a WaZOO             */
   /*--------------------------------------------------------------------*/

   if (requests_ok && remote_capabilities)
      {
      (void) sprintf (fname, request_template, HoldName, Hex_Addr_Str (&called_addr));
      if (!stat (fname, &buf))
         {
         if (!(((unsigned) remote_capabilities) & WZ_FREQ))
            status_line (MSG_TXT(M_FREQ_DECLINED));
         else
            {
            status_line (MSG_TXT(M_MAKING_FREQ));
            if (FTSC_callback (fname))
               (void) unlink (fname);
            }
         }
      }

   /*--------------------------------------------------------------------*/
   /* Process WaZOO file requests from other system                      */
   /*--------------------------------------------------------------------*/

   j = respond_to_file_requests (j, FTSC_callback, FTSC_time);

   /* Now close out the file attaches */
   sent_mail = 1;
   *sptr = 0;
   status_line (" %s %s %s", MSG_TXT(M_END_OF), MSG_TXT(M_OUTBOUND), MSG_TXT(M_FILE_ATTACHES));
  (void) Batch_Send (NULL);
   return TRUE;
}

int FTSC_recvmail (int outbound_session)
{
   char fname[80];
   char fname1[80];
   char fname2[80];
   struct _pkthdr tmppkt;
   FILE *fp, *fp1;
   int done;
   int j;
   char *starting_inbound;

   status_line (MSG_TXT(M_RECV_MAIL));

   if (!CARRIER)
      {
      status_line (MSG_TXT(M_NO_CARRIER));
      CLEAR_INBOUND ();
      return (1);
      }

   XON_DISABLE ();

   done = 0;

   /* If we don't want to pickup stuff */
   if (no_pickup)
      {
      status_line (MSG_TXT(M_NO_PICKUP));
      SENDBYTE (CAN);
      }
   else
      {
      status_line (" %s %s", MSG_TXT(M_INBOUND), MSG_TXT(M_MAIL_PACKET));
      /* Invent a dummy name for the packet */
      invent_pkt_name (fname1);

      /* Receive the packet with special netmail protocol */
      CLEAR_INBOUND ();

      starting_inbound = CURRENT.sc_Inbound;

      if (Xmodem_Receive_File (CURRENT.sc_Inbound, fname1) == 0)
         {
         got_packet = 1;
         }
      (void) sprintf (fname, "%s%s", starting_inbound, fname1);

      /* Check the password if there is one */
      if ((!remote_capabilities) &&
          (!outbound_session)    &&
          (n_getpassword (&remote_addr)))
         {
         if (remote_password != NULL)
            {
            got_packet = 0;
            if ((fp = fopen (fname, rb_plus)) == NULL)
               {
               (void) got_error (MSG_TXT(M_OPEN_MSG), fname);
               status_line (MSG_TXT(M_PWD_ERR_ASSUMED));
               return (1);
               }
            if (fread (&tmppkt, 1, sizeof (struct _pkthdr), fp) < sizeof (struct _pkthdr))
               {
               (void) got_error (MSG_TXT(M_OPEN_MSG), fname);
               status_line (MSG_TXT(M_PWD_ERR_ASSUMED));
               (void) fclose (fp);
               return (1);
               }
            (void) fclose (fp);
            if (n_password ((char *) (tmppkt.password), remote_password))
               {
               tmppkt.orig_zone = 0;
               (void) strcpy (fname1, fname);
               j = (int) strlen (fname) - 3;
               (void) strcpy (&(fname[j]), "Bad");
               if (rename (fname1, fname))
                  {
                  status_line (MSG_TXT(M_CANT_RENAME_MAIL), fname1);
                  }
               else
                  {
                  status_line (MSG_TXT(M_MAIL_PACKET_RENAMED), fname);
                  }
               return (1);
               }
            }
         got_packet = 1;
         }
  /*
   *  See if things changed after the fact. If so, we want to move
   *  the mail packet from the non-secured directory into the
   *  secured one. This is slightly tricky. Start with a simple rename
   *  and if that doesn't work (it might not if we're spanning drives)
   *  do a simple copy/unlink.
   *
   *  Steal resources such as 'done' and 'Secbuf' wherever that makes sense.
   */

      if (strcmp (starting_inbound, CURRENT.sc_Inbound) != 0)
         {
         (void) strcpy (fname2, CURRENT.sc_Inbound);
         (void) strcat (fname2, fname1);

     /*  Try the easy case first. A straight rename. */

         done = 1;

         if (rename (fname2, fname))
            {

     /*     If we get here, the straight rename didn't work. Let's
      *     do a copy. Use Secbuf since while we are here, we're
      *     not doing any file transfers.
      */
            done = 0;   /* default is failure till files are open */

            if ((fp = fopen (fname, rb_plus)) == NULL)
               {
               (void) got_error (MSG_TXT(M_OPEN_MSG), fname);
               }
            else
               if ((fp1 = fopen (fname2, "wb")) == NULL)
                  {
                  (void) got_error (MSG_TXT(M_OPEN_MSG), fname2);
                  }
               else /* Here both packets are open */
                    /* Steal Secbuf because nobody's using it now */
                  {
                  done = 1;   /* default is success now */

                  while ((j = fread (Secbuf, 1, WAZOOMAX, fp)) > 0)
                     {
                     if (fwrite (Secbuf, j, 1, fp1) != 1)
                        {
                        (void) got_error (MSG_TXT(M_WRITE_MSG), fname2);
                        done = 0;   /* only possible failure = write err */
                        break;
                        }
                     }
                  (void) fclose (fp1);

                  if (done == 0)  /* Figure out which file to delete */
                     (void) unlink (fname2);
                  else
                     (void) unlink (fname);
                  }
            }
         if (done == 0)
            status_line (MSG_TXT(M_CANT_RENAME_MAIL), fname);
         else
            status_line (MSG_TXT(M_MAIL_PACKET_RENAMED), fname2);
         }

  /*
   * If this was an inbound session, we need to set up the
   * node flags for the node.
   */
      got_mail = got_packet;
      if (!outbound_session)
         {
         if (flag_file (TEST_AND_SET, &remote_addr, 1))
            return (1);
         called_addr = remote_addr;
         }

       done = 0;
      /* Now receive the files if possible */
      status_line (" %s %s", MSG_TXT(M_INBOUND), MSG_TXT(M_FILE_ATTACHES));
      done = Batch_Receive (CURRENT.sc_Inbound);
      }

   status_line (" %s %s %s", MSG_TXT(M_END_OF), MSG_TXT(M_INBOUND), MSG_TXT(M_FILE_ATTACHES));
   CLEAR_INBOUND ();
   return (done);
}

int FTSC_callback (char *sptr)
{
   net_problems = Batch_Send (sptr);
   if (net_problems != 0)
      {
      net_problems = 1;
      return FALSE;
      }
   return TRUE;
}

int FTSC_time (long filesize)
{
   int i;
   i = (int) (filesize * 10 / cur_baud.rate_value * 100 / 94);
   return (i);
}