MAILOVLY.C

31.7 KB 3b159d711b96aad8…
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         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 Mail Control 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"

char mail_stat (MAILP);
int xmit_install (MAILP, ADDRP);
MAILP xmit_find (MAILP, ADDRP);
long netsize (MAILP);
int any_mail (MAILP);
void do_xmit_line (char *, MAILP);
void xmit_sort (void);
char *numdisp (long);

#ifdef MILQ
static char *HoldFmtStr = "%16.16s %4.4s %5.5s %c";
static char *HoldNoSize = "%21.21s %5.5s %c";
#else
static char *HoldFmtStr = "%-16.16s %4.4s %5.5s %c";
static char *HoldNoSize = "%-21.21s %5.5s %c";
#endif

void xmit_sameplace ()
{
   MAILP p, p1;

   /* Find the guy we just gave mail to */
   p = find_mail (&remote_addr);
   remote_addr.Zone = remote_addr.Net = remote_addr.Node = remote_addr.Point = 0;
   remote_addr.Domain = NULL;
   if (p == NULL)
      {
      /* He is not there */
      return;
      }

   /* Save our current pointer */
   p1 = next_mail;
   if (p != next_mail)
      {
      /* If it is not the one we just gave mail to, save ptr and delete */
      next_mail = p;
      xmit_delete ();
      next_mail = p1;
      }
   else
      {
      /* It was the guy at the head of the list, so just delete him */
      xmit_delete ();
      }

   /* If we came in with a null, leave with a null */
   if (p1 == NULL)
      next_mail = NULL;

   return;
}

MAILP find_mail (ADDRP address)
{
   MAILP p;

   p = mail_top;
   while (p != NULL)
      {
      if ((no_zones || (p->mail_addr.Zone == address->Zone)) &&
          (p->mail_addr.Net == address->Net) &&
          (p->mail_addr.Node == address->Node) &&
          (p->mail_addr.Point == address->Point) &&
          ((p->mail_addr.Domain == address->Domain) ||
           ((p->mail_addr.Domain == my_addr.Domain) &&
            (address->Domain == NULL))))
         break;
      p = p->next;
      }

   return (p);
}

int xmit_install (MAILP p, ADDRP addr)
{
   MAILP p1, p2;
   int rettype;
   long sztemp;

   p2 = find_mail (addr);

   if (p2 == NULL)
      {
      /* We didn't find it in what we have already */
      p1 = p;
      p1->mail_addr = *addr;
      rettype = 0;
      }
   else
      {
      /* We found it, so we have to make sure the higher level routine knows */
      p1 = p2;
      rettype = 1;
      }

/*
 * Get the size of the entry. If it's a FLO-type file,
 * call netsize to find out how big the stuff contained in it
 * actually is. If it's a packet, just take its size.
 *
 * Hold packets don't count.
 */

   if (!no_size)
      {
      sztemp = 0L;

      if (!strncmp (&(dta_str.name[10]), "LO", 2))
         p1->mailsize += (sztemp = netsize (p1));

      else
      if (!strncmp (&(dta_str.name[10]), "UT", 2))
         p1->mailsize += (sztemp = dta_str.size);

      if (dta_str.name[9] != 'H')
         p1->callsize += sztemp;
      }

   switch (dta_str.name[9])
      {
      case 'C':      /* Crash */
         p1->mailtypes |= MAIL_CRASH;
         break;

      case 'H':      /* Hold */
         p1->mailtypes |= MAIL_HOLD;
         break;

      case 'F':      /* Normal */
      case 'O':
         p1->mailtypes |= MAIL_NORMAL;
         break;

      case 'D':      /* Direct */
         p1->mailtypes |= MAIL_DIRECT;
         break;

      case 'R':      /* Request */
         p1->mailtypes |= MAIL_REQUEST;
         break;
      }

   if (!nodefind (&(p1->mail_addr), 0))
      {
      p1->mailtypes |= MAIL_UNKNOWN;
      return (rettype);
      }

   /* Don't call for "HOLD" or "REQ" stuff. */
   if ((dta_str.name[9] == 'H') || (dta_str.name[9] == 'R'))
      {
      return (rettype);
      }

   /* If there's no event, set mail to 'go' */
   if (cur_event < 0)
      {
      p1->mailtypes &= ~MAIL_QSMALL;
      p1->mailtypes |= MAIL_WILLGO;
      return (rettype);
      }

   /* If it is a crash only event and we have crashmail, set it to go */

   if (e_ptrs[cur_event].behavior & MAT_HIPRICM)
      {
      if ((dta_str.name[9] == 'C') && (newnodedes.NodeFlags & B_CM))
         {
         p1->mailtypes &= ~MAIL_QSMALL;
         p1->mailtypes |= MAIL_WILLGO;
         return (rettype);
         }
      }

   /* If it is a crash only event and this wasn't crash, return */
   if ((dta_str.name[9] != 'C') && (e_ptrs[cur_event].behavior & MAT_CM))
      {
      return (rettype);
      }

   /* Is this a local only event? */
   if (e_ptrs[cur_event].behavior & MAT_LOCAL)
      {
      /*
       * If this is supposed to be only local, then get out if it isn't 
       */
      if (e_ptrs[cur_event].node_cost >= 0)
         {
         if ((int) newnodedes.RealCost > e_ptrs[cur_event].node_cost)
            {
            return (rettype);
            }
         }
      else
         {
         if ((int) newnodedes.RealCost < -(e_ptrs[cur_event].node_cost))
            {
            return (rettype);
            }
         }
      }

   /* Is this a non-mail window event? */
   if ((newnodelist || version7) && 
       (!(e_ptrs[cur_event].behavior & MAT_NOMAIL24)))
      {
      /* If this guy can't handle crash, get out and try again */
      if (!(newnodedes.NodeFlags & B_CM))
         {
         return (rettype);
         }
      }

   /* Is this a receive only event? */
   if (e_ptrs[cur_event].behavior & MAT_NOOUT)
      {
      return (rettype);
      }

   /* Is this a non-CM event? */
   if ((newnodelist || version7) &&
       (e_ptrs[cur_event].behavior & MAT_NOCM) &&
       (newnodedes.NodeFlags & B_CM))
      {
      return (rettype);
      }

   /* See if we spent too much calling him already */
   if (bad_call (&(p1->mail_addr), 0))
      {
      p1->mailtypes |= MAIL_TOOBAD;
      return (rettype);
      }

   /* See if we have enough mail to send */
   if (!no_size && e_ptrs[cur_event].mailqsize > p1->callsize)
      {
      p1->mailtypes |= MAIL_QSMALL;
      return(rettype);
      }

   p1->mailtypes &= ~MAIL_QSMALL;
   p1->mailtypes |= MAIL_WILLGO;

   return (rettype);
}

char mail_stat (MAILP p)
{
   if (p->mailtypes & MAIL_UNKNOWN)
      return ('!');
   if (p->mailtypes & MAIL_TOOBAD)
      return ('x');
   if (p->mailtypes & MAIL_TRIED)
      return ('#');
   if (p->mailtypes & MAIL_WILLGO)
      return ('*');
   if (p->mailtypes & MAIL_QSMALL)
      return ('<');
   return ('-');
}

char *mail_status_chars (unsigned int);

char msc[10];

char *mail_status_chars (unsigned int p)
{
   char *q;

   q = msc;

   if (p & MAIL_CRASH  )
      *q++ = 'C';
   if (p & MAIL_HOLD   )
      *q++ = 'H';
   if (p & MAIL_DIRECT )
      *q++ = 'D';
   if (p & MAIL_NORMAL )
      *q++ = 'N';
   if (p & MAIL_REQUEST)
      *q++ = 'R';
   *q++ = '\0';

   return (msc);
}

void xmit_window (MAILP p1)
{
   MAILP p;
   int i;
   char j1[32];
   char                *jPtr;

#ifdef MILQ
   RECT                 Rect;
   int                  Width;
#endif

   if (!fullscreen)
      return;

   p = p1;

   sb_fillc (hold_hWnd, ' ');
   jPtr = j1;
#ifdef MILQ
   GetClientRect( hold_hWnd, &Rect );
   SB_ROW_HOLD = Rect.bottom + 2;
   if ( 30 > ( Width = Rect.right - Rect.left ) )
     jPtr += 30 - Width;
#endif

   if (p == NULL)
      {
      sb_move (hold_hWnd, 3, 5);
      SendMessage( hold_hWnd, WM_COMMAND, GD_MODE, 0L );
      SendMessage( hold_hWnd, WM_COMMAND, GD_CLR, 0L );
      sb_puts( hold_Init, MSG_TXT(M_NOTHING_IN_OUTBOUND) );
      return;
      }

   SendMessage( hold_hWnd, WM_COMMAND, GD_MODE, 1L );
   SendMessage( hold_hWnd, WM_COMMAND, GD_CLR, 0L );

#ifdef MILQ
   if ( hold_hWnd == GetFocus() )
     SendMessage( node_hWnd, WM_COMMAND, GD_PND, (long)&p->mail_addr );
#endif

   strcpy( j1, MSG_TXT(M_OUTBOUND_HEADER) );
   sb_move (hold_hWnd, 1, 2);
   sb_puts( hold_Hdr, jPtr);
   for (i = 2; i < SB_ROW_HOLD; i++)
      {
      if (p == NULL)
         break;

      do_xmit_line (j1, p);

      sb_move (hold_hWnd, i, 2);
      sb_puts( HoldWndDtl(i), jPtr);
      p = p->next;
      }

   p = mail_top;

   for (; i < SB_ROW_HOLD; i++)
      {
      if ((p == p1) || (p == NULL))
         break;

      do_xmit_line (j1, p);

      sb_move (hold_hWnd, i, 2);
      sb_puts( HoldWndDtl(i), jPtr);
      p = p->next;
      }
   SendMessage( hold_hWnd, WM_COMMAND, GD_CLR, (long)i );
   sb_show ();
}

void do_xmit_line (char *line, MAILP p)
{
   if (no_size)
      {
      (void) sprintf (line, HoldNoSize,
         Full_Addr_Str (&(p->mail_addr)),
         mail_status_chars (p->mailtypes),
         mail_stat (p));
      }
   else
      {
      (void) sprintf (line, HoldFmtStr,
         Full_Addr_Str (&(p->mail_addr)),
         numdisp (p->mailsize),
         mail_status_chars (p->mailtypes),
         mail_stat (p));
      }
}


void xmit_sort ()
{
   MAILP p, p1, p2;

   p = mail_top;

   /* Find the first that is sendable */
   while (p != NULL)
      {
      if ((p->mailtypes & MAIL_WILLGO) &&
         (!(p->mailtypes & MAIL_TOOBAD)) &&
         (!(p->mailtypes & MAIL_UNKNOWN)))
         break;
      p = p->next;
      }

   if (p == NULL)
      return;

   /* Put the first sendable one on top */
   if (p != mail_top)
      {
      p->prev->next = p->next;
      if (p->next != NULL)
         p->next->prev = p->prev;
      p->prev = NULL;
      p->next = mail_top;
      mail_top->prev = p;
      mail_top = p;
      }

   p1 = p;
   p = p1->next;
   while (p != NULL)
      {
      if ((p->mailtypes & MAIL_WILLGO) &&
         (!(p->mailtypes & MAIL_TOOBAD)) &&
         (!(p->mailtypes & MAIL_UNKNOWN)))
         {
         if (p->prev == p1)
            {
            p1 = p;
            p = p->next;
            continue;
            }
         p2 = p->next;
         p->prev->next = p->next;
         if (p->next != NULL)
            p->next->prev = p->prev;
         p->next = p1->next;
         if (p1->next != NULL)
            p1->next->prev = p;
         p->prev = p1;
         p1->next = p;
         p1 = p;
         p = p2;
         }
      else
         {
         p = p->next;
         }
      }
}

void xmit_reset ()
{
   MAILP p;
   int j, k, done, zone;
   char *q, *s;
   char *domain;
   char *HoldName;
   char pointspec[128];
   ADDR tmp;
   struct FILEINFO zone_dir;
   struct FILEINFO pnt_dir;
   long longzone;

   /* First get rid of all the old junk */
   p = mail_top;
   if (p != NULL)
      {
      while (p->next != NULL)
         p = p->next;
      while (p->prev != NULL)
         {
         p = p->prev;
         free (p->next);
         }
      if (p != NULL)
         free (p);
      }

   p = mail_top = NULL;

/*
 * Initialize domain to scan. Choose (of course) the
 * domain of our primary address.
 *
 * This domain is special in that its outbound is hold_area.
 * All the other domains use their abbreviation as the name
 * of their outbounds.
 */


   k = 0;
   domain = domain_name[0];
   (void) strcpy (pointspec, hold_area);
   q = &(pointspec[strlen (pointspec)]) - 1;
   do
      {
/*
 * Initialize scan of zones in this domain. Using findfirst/findnext,
 * get all the matching directories.
 */
      (void) strcpy (q, ".*");
      j = 0;
      while (!dfind (&zone_dir, pointspec, j))
         {
         j = 1;                 /* Flip findfirst/findnext to findnext */
/*
 * We have a match on the outbound spec. Make sure it's a directory.
 *
 * Then:
 *
 *       1) If no extension, we may only use it if this is alias 0
 *       2) If an extension, it must be a 3-digit hex number
 *
 * If the extension passes one of these tests, get to work!
 */
         if (!(zone_dir.attr & FA_SUBDIR))
            continue;

         q = strchr (zone_dir.name, '.');
         if (q == NULL)
            {
            if (k != 0 && !no_zones)
               continue;
            zone = (int) alias[0].Zone;
            }
         else
            {
            if (no_zones)
               continue;
            s = ++q;
            longzone = strtol (q, &q, 16);
            if ((s + 3) != q)
               continue;
            zone = (int) longzone;
            }
/*
 * OK. We have a domain, an outbound directory, and a zone.
 * That means there's an outbound to scan.
 *
 * Start by scanning the nodes.               
 */
         tmp.Zone = zone;
         tmp.Domain = domain;
         tmp.Net = tmp.Node = tmp.Point = 0;
         p = xmit_find (p, &tmp);
/*
 * Now we do the points contained in this outbound.
 *
 */
         if (pvtnet <= 0)
            {
            HoldName = HoldAreaNameMunge (&tmp);
            (void) sprintf (pointspec, "%s*.PNT", HoldName);
            j = 0;
            done = 0;

            while (!done)
               {
               /* See if we have any more at this level */
               if (dfind (&pnt_dir, pointspec, j++))
                  {
                  /* No more at this level, so go to next level */
                  done = 1;
                  }
               else
                  {
                  if (sscanf (pnt_dir.name, "%04x%04x.", &(tmp.Net), &(tmp.Node)) != 2)
                     continue;
                  tmp.Point = 1;
                  p = xmit_find (p, &tmp);

                  } /* got one */
               } /* while (!done) */
            }
         } /* while !dfind (...) to get outbounds */
/*
 * See if there are any more domains. If so, set up the right name
 * for the outbound, so we can find 'em.
 */
      if ((domain = domain_name[++k]) != NULL)
         {
         *domain_loc = '\0';
         (void) strcpy (pointspec, domain_area);
         q = &(pointspec[strlen (pointspec)]);
         s = domain_abbrev[k];
         if (s != NULL)
             while (*s)
                 *q++ = *s++;
         }
      } while (domain != NULL);
   next_mail = NULL;
   xmit_sort ();
   xmit_window (mail_top);
   next_rescan = (long) time (NULL) + 600L; /* At least 10 min to next scan */
}

MAILP xmit_find (MAILP p, ADDRP address)
{
   int j;
   char next_one [127];
   char *HoldName;
   ADDR tmp;

   tmp = *address;

   HoldName = HoldAreaNameMunge (address);

   if (address->Point != 0)
      {
      (void) sprintf (next_one, "%s%04x%04x.PNT\\*.*",
                HoldName, address->Net, address->Node);
      tmp.Point = 0;
      }
   else
      {
      (void) sprintf (next_one, "%s*.*", HoldName);
      tmp.Net = 0;
      tmp.Node = 0;
      tmp.Point = 0;
      }

   j = 0;

   while (!dfind (&dta_str, next_one, j))
      {
      j = 1;

      /* We have a match. Was it a .FLO file or a .OUT file? */
      if (strncmp (&(dta_str.name[10]), "LO", 2) == 0)
         {
         /* FLO, DLO, CLO and HLO are the only ones! */
         if (strchr ("FDCH", dta_str.name[9]) == NULL)
             continue;
         }
      else
      if (strncmp (&(dta_str.name[10]), "UT", 2) == 0)
         {
         /* OUT, DUT, CUT and HUT are the only ones! */
         if (strchr ("ODCH", dta_str.name[9]) == NULL)
             continue;
         }
      else
      if (strncmp (&(dta_str.name[9]), "REQ", 3) != 0)
         continue;


      /* We found a name, remember it */
      if (address->Point != 0)
         {
         if (sscanf (dta_str.name, "%08x.", &(tmp.Point)) != 1)
            continue;
         }
      else if (sscanf (dta_str.name, "%04x%04x.", &(tmp.Net), &(tmp.Node)) != 2)
              continue;

      if (p == NULL)
         {
         p = mail_top = (MAILP) calloc (sizeof (MAIL), 1);
         }
      else
         {
         p->next = (MAILP) calloc (sizeof (MAIL), 1);
         p->next->prev = p;
         p = p->next;
         }

      if (xmit_install (p, &tmp))
         {
         /* No good */
         if (p->prev != NULL)
            {
            p = p->prev;
            free (p->next);
            p->next = NULL;
            }
         else
            {
            free (p);
            p = mail_top = NULL;
            }
         }

      } /* while (!done) */
   return (p);
}

int xmit_next (ADDRP xaddr)
{
   int i, j;

   for (i = 0; i < 2; i++)
      {
      /* Set up the proper pointer */
      if ((next_mail == NULL) || (next_mail->next == NULL))
         {
         if (next_rescan < (long) time (NULL))
            xmit_reset ();
         next_mail = mail_top;
         }
      else
         {
         next_mail = next_mail->next;
         }
   
      /* Loop through till we find something we can send */
      while (next_mail != NULL)
         {
         if ((next_mail->mailtypes & MAIL_WILLGO) &&
             (!(next_mail->mailtypes & MAIL_UNKNOWN)) &&
             (!(next_mail->mailtypes & MAIL_TOOBAD)))
            {
            if (bad_call (&(next_mail->mail_addr), 0))
               {
               next_mail->mailtypes |= MAIL_TOOBAD;
               }
            else
               {
               /* If multitasking, check for mail before calling */
               if ((TaskNumber != 0) && ((j = any_mail (next_mail)) <= 0))
                  {
                  if (j == 0)
                     xmit_delete ();
                  else next_mail = next_mail->next;
                  continue;
                  }
               *xaddr = next_mail->mail_addr;
               xmit_window (next_mail);
               return (1);
               }
            }
         next_mail = next_mail->next;
         }
      }
   /* Oh well, we tried */
   xmit_window (mail_top);
   return (0);
}

void xmit_delete ()
{
   MAILP p;

   if (next_mail == NULL)
      return;

   if (any_mail (next_mail) != 0)
         {
         status_line (MSG_TXT(M_STILL_HAVE_MAIL), Full_Addr_Str (&(next_mail->mail_addr)));
         /* We still have something for him */
         next_mail->mailtypes &= ~MAIL_WILLGO;
         next_mail->mailtypes |= MAIL_TRIED;
         return;
         }

   if (next_mail != mail_top)
      {
      p = next_mail->next;
      next_mail = next_mail->prev;
      free (next_mail->next);
      next_mail->next = p;
      if (p != NULL)
         p->prev = next_mail;
      xmit_window (next_mail);
      }
   else
      {
      mail_top = mail_top->next;
      free (next_mail);
      if (mail_top != NULL)
         mail_top->prev = NULL;
      xmit_window (mail_top);
      next_mail = NULL;
      }
}

int bad_call (ADDRP baddr, int rwd)
{
   int res;
   int i, j;
   struct FILEINFO bad_dta;
   FILE *bad_wazoo;
   char *p;
   char *HoldName;

   char fname[128];
   char fname1[128];

   HoldName = HoldAreaNameMunge(baddr);
   (void) sprintf (fname, "%s%s.$$?", HoldName, Hex_Addr_Str (baddr));
   j = (int) strlen (fname) - 1;                 /* Point at ?          */
   res = -1;                                     /* Initialize to fail  */

   i = 0;                                        /* This says findfirst */
   while (!dfind (&bad_dta, fname, i))           /* as long as we match */
      {
      if (isdigit (bad_dta.name[11]))            /* is there a digit?   */
         {
         fname[j] = bad_dta.name[11];            /* Yes, copy to fname  */
         res = fname[j] - '0';                   /* Save it for testing */
         break;                                  /* Get out of while    */
         }
      else i = 1;                                /* Else use findnext   */
      }

   if (res == -1)                                /* Successful search?  */
      {
      fname[j] = '0';                            /* No, base digit = 0  */
      }

   if (rwd > 0)
      {
      /* Writing a bad call  */

      /* First create a filename that is one higher than what we've got */
      (void) strcpy (fname1, fname);
      fname1[j]++;
      if (fname1[j] > '9')
         fname1[j] = '9';

      if (res == -1)                             /* Did we have a file? */
         {                                       /* No, make one.       */
         if (rwd == 2)                           /* No carrier */
            res = open (fname, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
         else /* With carrier */
            res = open (fname1, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
         i = rwd - 1;                            /* zero-based count    */
         (void) write (res, (char *) &i, sizeof (int)); /* write it out        */
         (void) close (res);                            /* close the file      */
         }
      else
         {                                       /* There was a file    */

         /*
          * 2 = Unsuccessful, No carrier. Update contents of the file.
          */

         if (rwd == 2)
            {
            i = open (fname, O_RDONLY|O_BINARY);
            (void) read (i, (char *) &res, sizeof (int));
            (void) close (i);

            ++res;

            i = open (fname, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
            (void) write (i, (char *) &res, sizeof (int));
            (void) close (i);
            }

         /*
          * 1 = Unsuccessful, Carrier. Update file name to reflect the
          * failure.
          */

         else
            {
            (void) rename (fname, fname1);
            }
         }
      }
   else if (rwd == 0)
      {

      /*
       * 0 = We are reading a bad call status
       */

      /* Is it automatically ok (no .$$ file there) ? */
      if (res == -1)
         return (0);

      /* Were there too many connects with carrier? */
      if (res >= max_connects)
         return (1);

      /* Ok, check for connects without carrier */
      res = 0;
      i = open (fname, O_RDONLY|O_BINARY);
      (void) read (i, (char *) &res, sizeof (int));
      (void) close (i);
      return (res >= max_noconnects);
      }
   else
      {

      /*
       * -1 = Cleanup of bad call status. This happens in two steps:
       * a) delete 'netnode.$$?' in hold area;
       * b) if a 'netnode.Z' file exists in hold area,
       *    1) delete all BADWAZOO.xxx files listed in the .Z file;
       *    2) delete the 'netnode.z' file.
       */

      if (res != -1)
         {
         (void) unlink (fname);
         }

      if (!mail_finished)
         return (0);

      (void) sprintf (fname, "%s%s.Z", HoldName, Hex_Addr_Str (baddr));
      if (dexists (fname))
         {
         if ((bad_wazoo = fopen (fname, read_ascii)) == NULL)
            {
            (void) got_error (MSG_TXT(M_OPEN_MSG), fname);
            }
         else
            {
            while (!feof (bad_wazoo))
               {
               e_input[0] = '\0';
               if (!fgets (e_input, 64, bad_wazoo))
                  break;
               /* Point to BADWAZOO.xxx */
               p = strchr (e_input, ' ') + 1;
               /* Then just past it and terminate */
               p = strchr (p, ' ');
               *p = '\0';
               /* Back to where we were */
               p = strchr (e_input, ' ') + 1;

               /* Build file name and delete file */
               (void) strcpy (fname1, CURRENT.sc_Inbound);
               (void) strcat (fname1, p);
               (void) unlink (fname1);
               }
            (void) fclose (bad_wazoo);
            }
         (void) unlink (fname);
         }
      }
   return (0);
}

void set_up_outbound ()
{
   MAILP mp;

   xmit_reset ();

   /* and remember where we left off */
   if (hist.next_addr.Net != 0)
      {
      next_addr = hist.next_addr;
      next_addr.Domain = NULL;
      mp = find_mail (&next_addr);
      if ((mp == NULL) || (mp->prev == NULL))
         {
         next_mail = NULL;
         xmit_window (mail_top);
         }
      else
         {
         next_mail = mp->prev;
         xmit_window (next_mail);
         }
      }
   else
      {
      next_addr.Zone = 0;
      next_addr.Net = 0;
      next_addr.Node = 0;
      next_addr.Point = 0;
      next_addr.Domain = NULL;
      xmit_window (mail_top);
      }
}
/*
 * Calculate size of mail queued for outbound.
 * Used to determine whether or not we have enough
 * mail to merit an outbound call.
 *
 * The original version of this code was donated by Henry Clark.
 */

long netsize (MAILP p)
{
    struct stat stbuf;
    char net_path[127];
    char *ptr;
    FILE *temp;
    long accum = 0L;
    char *q;

    /* Append the ARCmail file name to the path line  */
    (void) sprintf (net_path, "%s%s.%s",
               HoldAreaNameMunge(&(p->mail_addr)),
               Hex_Addr_Str (&(p->mail_addr)),
               &dta_str.name[9]);

    temp = share_fopen (net_path, "rb", DENY_WRITE);

    if (temp == (FILE *)NULL)
        return (accum);

    while (!feof (temp))
        {
/*
 *      Make sure of a nice zero there if we're at an undetected EOF.
 *      Then try to read a line from the file.
 */
        net_path[0] = '\0';
        (void) fgets (net_path, 79, temp);
/*
 *      Clean up anything we don't want to see (blanks, tabs, CR, etc)
 */
        for (q = ptr = net_path; *q; q++)
            if (*q <= ' ')
                *q = '\0';
/*
 *      File disposition commands should be skipped over to get to
 *      actual filenames.
 */
        if ((*ptr == TRUNC_AFTER)       ||
            (*ptr == DELETE_AFTER)      ||
            (*ptr == SHOW_DELETE_AFTER) ||
            (*ptr == NOTHING_AFTER))
            ptr++;
/*
 *      Now -- if what's left starts with a semicolon, it's a comment.
 *      If it starts with a tilde, the file has already been sent. If
 *      what we see is a zero, there's nothing on the line. In any one
 *      of these cases, we should skip this line.
 */
        if ((*ptr == '\0')              ||
            (*ptr == ';')               ||
            (*ptr == '~'))
            continue;
/*
 *      Get the file size by doing a stat call. If it's not there
 *      then we obviously need not add any size in.
 */
        if (stat (ptr, &stbuf))            /* file exist? */
            continue;
        else accum += stbuf.st_size;
        }
    (void) fclose (temp);
    return (accum);
}

/*
 * Figure out if there's any mail for the specified node.
 * Used to determine if we need to actually make a call.
 *
 * Returns 0 for no mail at all
 *         1 for non-hold mail
 *        -1 for hold mail only
 *
 * I can't remember who was the first to demand this. I've been
 * pummelled for a while and there's almost certainly been a loss
 * of grey matter.
 */

int any_mail (MAILP node)
{
   struct FILEINFO dta;
   char next_one [127];
   int ret = 0;

   (void) sprintf (next_one, "%s%s.*",
            HoldAreaNameMunge(&(node->mail_addr)),
            Hex_Addr_Str (&(node->mail_addr)));

   if (dfind (&dta, next_one, 0))
      return (0);

   do
      {
#ifndef JACK_DECKER
      if (dta.name[9] == 'H')
         {
         ret = -1;
         continue;
         }
#endif
      if (!strncmp (&(dta.name[10]), "LO", 2))
          return (1);

      if (!strncmp (&(dta.name[10]), "UT", 2))
          return (1);
      } while (!dfind (&dta, next_one, 1));

   return (ret);
}

/*
 * Create a small character string for mailsize.
 */

static char e_shit[6];
static char *descriptor = "bKMG";

char *numdisp (long number)
{
    int i = 0;
    char tempstr[6];
    long quotient, oldq;
    int intq;

    oldq = 0L;
    quotient = number;

    while (quotient >= 1024L)
        {
        oldq = quotient;
        quotient = oldq / 1024L;
        i++;
        }

    intq = (int) quotient;

  /*
   * If more than 999 but less than 1024, it's a big fraction of
   * the next power of 1024. Get top two significant digits
   * (so 1023 would come out .99K, for example)
   */


    if (intq > 999)
        {
        intq = (intq * 25) / 256; /* 100/1024 */
        (void) sprintf (e_shit, ".%2d%c", intq, descriptor[++i]);
        }
  /*
   * If less than 10 and not small units, then get some decimal
   * places (e.g. 1.2M)
   */

    else if ((intq < 10) && (i != 0))
       {
       intq = (int) ((oldq * 5L) / 512L); /* 10/1024 */
       (void) sprintf (tempstr, "%02d", intq);
       (void) sprintf (e_shit, "%c.%c%c", tempstr[0], tempstr[1], descriptor[i]);
       }
  /*
   * Simple case. Just do it.
   */

    else (void) sprintf (e_shit, "%3d%c", intq, descriptor[i]);

    return (e_shit);
}