home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / bts314b4 / mailer.c < prev    next >
C/C++ Source or Header  |  1994-09-12  |  61KB  |  2,723 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-90, Bit Bucket Software Co., a Delaware Corporation. */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                 This module was written by Bob Hartman                   */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*                   BinkleyTerm Mail Control Routines                      */
  17. /*                                                                          */
  18. /*                                                                          */
  19. /*    For complete  details  of the licensing restrictions, please refer    */
  20. /*    to the License  agreement,  which  is published in its entirety in    */
  21. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.240.    */
  22. /*                                                                          */
  23. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  24. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  25. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  26. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  27. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  28. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  29. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  30. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  31. /*                                                                          */
  32. /*                                                                          */
  33. /* You can contact Bit Bucket Software Co. at any one of the following      */
  34. /* addresses:                                                               */
  35. /*                                                                          */
  36. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:132/491, 1:141/491  */
  37. /* P.O. Box 460398                AlterNet 7:491/0                          */
  38. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  39. /*                                Internet f491.n132.z1.fidonet.org         */
  40. /*                                                                          */
  41. /* Please feel free to contact us at any time to share your comments about  */
  42. /* our software and/or licensing policies.                                  */
  43. /*                                                                          */
  44. /*--------------------------------------------------------------------------*/
  45.  
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <time.h>
  50. #include <signal.h>
  51. #include <ctype.h>
  52. #include <conio.h>
  53. #ifdef __TOS__
  54. #include <ext.h>
  55. #else
  56. #include <sys/types.h>
  57. #include <sys/stat.h>
  58. #include <fcntl.h>
  59. #include <dos.h>
  60. #endif
  61. #ifndef LATTICE
  62. #include <process.h>
  63. #endif
  64. #ifdef LATTICE
  65. #undef min
  66. #else
  67. #include <io.h>
  68. #endif
  69.  
  70. #include "bink.h"
  71. #include "msgs.h"
  72. #include "sbuf.h"
  73. #include "com.h"
  74. #include "vfossil.h"
  75. #include "sched.h"
  76. #include "keybd.h"
  77. #include "zmodem.h"
  78. #include "session.h"
  79. #include "nodeproc.h"
  80.  
  81. /*
  82.  * Data (used to be in data.c but it is only ever used in here!)
  83.  */
  84.  
  85. static struct FILEINFO dta_str = { 0 };
  86. static char next_one[64];
  87.  
  88. static ADDR next_addr;            /* Next address to call */
  89.  
  90.  
  91.  
  92. /*--------------------------------------------------------------------------*/
  93. /*                                                                          */
  94. /*                    (C) Copyright 1990, Holger Schurig                    */
  95. /*                                                                          */
  96. /*                This module was written by Holger Schurig                 */
  97. /*                                                                          */
  98. /*                          Zoomed Outbound Window                          */
  99. /*                                                                          */
  100. /* Minor modifications for Atari ST by Steven Green                         */
  101. /*--------------------------------------------------------------------------*/
  102.  
  103. static void zoom_window (REGIONP zoomwin, MAILP p)
  104. {
  105.     int i,n;
  106.     long l;
  107.     char out_str[50];
  108.     char flagstr[7];
  109.  
  110.     /* clear the inside of zoomed outbound */
  111.     zoomwin->sr0++;
  112.     zoomwin->sr1--;
  113.     zoomwin->sc0++;
  114.     zoomwin->sc1--;
  115.     sb_fillc (zoomwin, ' ');
  116.     zoomwin->sr0--;
  117.     zoomwin->sr1++;
  118.     zoomwin->sc0--;
  119.     zoomwin->sc1++;
  120.  
  121.     /* give it a header */
  122.     sb_move (zoomwin, 1, 2);
  123.     sb_puts (zoomwin,"Node            Domain          Files Bytes Age Calls Bad Status Errors");
  124.  
  125.     for(i = 2; i < (zoomwin->r1 - zoomwin->r0); i++)
  126.     {
  127.         if (p == NULL)
  128.             break;
  129.  
  130.         sb_move (zoomwin, i, 2);
  131.         sprintf (out_str, "%u:%u/%u",
  132.             p->mail_addr.Zone,
  133.             p->mail_addr.Net,
  134.             p->mail_addr.Node);
  135.         if(p->mail_addr.Point)
  136.             sprintf(&out_str[strlen(out_str)], ".%u", p->mail_addr.Point);
  137.         sb_puts (zoomwin, (unsigned char *) out_str);
  138.  
  139.         if (p->mail_addr.Domain != NULL)
  140.         {
  141.             sb_move (zoomwin, i, 18);
  142.             sprintf (out_str, "%-15s", p->mail_addr.Domain);
  143.             sb_puts (zoomwin, fancy_str(out_str));
  144.         }
  145.         sb_move (zoomwin, i, 34);
  146.  
  147.         n = 0;
  148.         if (  p->mailtypes & MAIL_HOLD    ) flagstr[n++] = 'H';
  149.         if (  p->mailtypes & MAIL_NORMAL  ) flagstr[n++] = 'N';
  150.         if (  p->mailtypes & MAIL_CRASH   ) flagstr[n++] = 'C';
  151.         if (  p->mailtypes & MAIL_DIRECT  ) flagstr[n++] = 'D';
  152.         if (  p->mailtypes & MAIL_REQUEST ) flagstr[n++] = 'R';
  153.         if (!(p->mailtypes & MAIL_WILLGO )) flagstr[n++] = '-';
  154.         flagstr[n] = '\0';
  155.  
  156.         l = ((long) time (NULL)) - (p->oldest);
  157.         n = (int) (l / 86400L);
  158.         sprintf (out_str, "%-3u %7lu %3d %5u %3u %6s",
  159.         p->files,
  160.         p->size,
  161.         (n > 999) ? 999 : n,
  162.         p->calls,
  163.         p->costcalls,
  164.         flagstr);
  165.         sb_puts (zoomwin, out_str);
  166.  
  167.         sb_move (zoomwin, i, 67);
  168.         out_str[0] = '\0';
  169.         if (p->mailtypes & MAIL_UNKNOWN)
  170.             sprintf (out_str, "Unknwn");
  171.         else
  172.             if (p->mailtypes & MAIL_TOOBAD)
  173.                 sprintf (out_str, "NoConn");
  174.             else
  175.                 if (p->mailtypes & MAIL_TRIED)
  176.                     sprintf (out_str, "Tried");
  177.         sb_puts (zoomwin, out_str);
  178.  
  179.         p = p->next;
  180.     }
  181.     sb_show ();
  182. }
  183.  
  184. static void extended_dodir(char *domain, int zone, REGIONP zoomwin)
  185. {
  186.     MAILP p;
  187.     ADDR tmp;
  188.     int i, j;
  189. #ifdef ATARIST
  190.     struct FILEINFO dta;
  191. #else
  192.     struct find_t dta;
  193. #endif
  194.     struct tm dt;
  195.     time_t unixdt;
  196.     struct stat statbuf;
  197. #ifdef IOS
  198.     int oat;
  199.     int opt,oft,ort;
  200. #endif
  201.     int out, flo, req, bad;
  202.     char *e1, *e2, *e3;
  203.     FILE *fp;
  204.     char fname[80];
  205.     char *fnameptr;
  206.  
  207.     tmp.Zone = zone;
  208.     tmp.Net = 
  209.     tmp.Node = 
  210.     tmp.Point = 0;
  211.     tmp.Domain = domain;
  212.     (void) sprintf (next_one, "%s*.*", HoldAreaNameMunge(&tmp));
  213.  
  214. #ifdef DEBUG
  215.     status_line(">extended_dodir(%s %d) => %s", domain ? domain : "", zone, next_one);
  216. #endif
  217.  
  218. #ifdef ATARIST
  219.     j = dfind(&dta, next_one, 0);
  220.     for (; !j; j = dnext (&dta))
  221. #else
  222.     j = _dos_findfirst (next_one, _A_ARCH | _A_NORMAL, &dta);
  223.     for (; !j; j = _dos_findnext (&dta))
  224. #endif
  225.     {
  226.         e1 = strchr(dta.name, '.');
  227.         if(e1 != NULL)
  228.         {
  229.             e1 = e1+1;
  230.             e2 = e1+1;
  231.             e3 = e2+1;
  232.             out = flo = req = bad = 0;
  233. #ifdef IOS
  234.             oat = 0;
  235.             opt = oft = ort = 0;    
  236.             if (                (*e2 == 'A') && (*e3 == 'T')) oat++;
  237.             if (                (*e2 == 'P') && (*e3 == 'T')) opt++;
  238.             if (                (*e2 == 'F') && (*e3 == 'T')) oft++;
  239.             if (                (*e2 == 'R') && (*e3 == 'T')) ort++;
  240. #endif
  241.             if (                (*e2 == 'U') && (*e3 == 'T')) out++;
  242.             if (                (*e2 == 'L') && (*e3 == 'O')) flo++;
  243.             if ((*e1 == 'R') && (*e2 == 'E') && (*e3 == 'Q')) req++;
  244.             if ((*e1 == '$') && (*e2 == '$')                ) bad++;
  245.  
  246. #ifdef IOS
  247.             if (out || flo || req || bad || oat || opt || oft || ort)
  248. #else
  249.             if (out || flo || req || bad)
  250. #endif
  251.             {
  252.  
  253.                 /* Decode the address */
  254.  
  255. #ifdef IOS
  256.                 if(oat || opt || oft || ort || (bad && iosmode))
  257.                     getaddress(dta.name, &tmp.Net, &tmp.Node, &tmp.Point);
  258.                 else
  259. #endif
  260.                     if(get2daddress(dta.name, &tmp) == FALSE)
  261.                         continue;    /* Ignore invalid addresses */
  262.  
  263.                 /* Display where we're at */
  264.  
  265.                 {
  266.                     if (fullscreen)
  267.                     {
  268.                         char s[40];
  269.                     
  270.                         sprintf(s, "%-30s", Pretty_Addr_Str(&tmp));
  271.  
  272.                         if(zoomwin)
  273.                         {
  274.                             sb_move(zoomwin, 2, 2);
  275.                             sb_puts(zoomwin, s);
  276.                         }
  277.                         else
  278.                         {
  279.                             sb_move(holdwin, 4, 2);
  280.                             sb_puts(holdwin, s);
  281.                         }
  282.                         sb_show();
  283.                     }
  284.                 }
  285.  
  286.                 /* Adresse suchen */
  287.                 
  288.                 p = find_mail (&tmp);
  289.                 if (p == NULL)
  290.                     continue;
  291.             }
  292.  
  293.  
  294.             /*
  295.              * If its not a $$ file
  296.              * Find out more about it!
  297.              */
  298.  
  299. #ifdef IOS
  300. #ifdef NEW
  301.             if (out || flo || req || oat || opt || oft || ort)
  302. #else
  303.             if (out || flo || req || oat)
  304. #endif
  305. #else
  306.             if (out || flo || req)
  307. #endif
  308.             {
  309.                 /* Filedatum setzen */
  310. #ifdef ATARIST
  311.                 dt.tm_year = (int)(((dta.time >> 9) & 0x7f) + 80);
  312.                 dt.tm_mon  = (int)(((dta.time >> 5) & 0xf) - 1);                                                    /* 0..11 */
  313.                 dt.tm_mday = (int)(dta.time & 0x1f);                                                              /* 1..31 */
  314. #else
  315.                 dt.tm_year = (dta.wr_date >> 9) + 80;
  316.                 dt.tm_mon  = ((dta.wr_date >> 5) & 0xf) - 1;                                                    /* 0..11 */
  317.                 dt.tm_mday = dta.wr_date &0x1f;                                                                 /* 1..31 */
  318. #endif
  319.                 dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
  320. #if defined(__TURBOC__) && !defined(__TOS__)  /* JCE 09.10.90 */
  321.                 unixdt = time (&dt);
  322. #else
  323.                 unixdt = mktime (&dt);
  324. #endif
  325.                 p->oldest = min(unixdt, p->oldest);
  326.             }
  327.  
  328.             /* NOT flow files */
  329.  
  330. #ifdef IOS
  331.             if(out || req || oat || opt || ort)
  332. #else
  333.             if (out || req)
  334. #endif
  335.             {
  336.                 /* Filelänge/Fileanzahl addieren */
  337.                 (p->files)++;
  338.                 (p->size) += dta.size;
  339.             }
  340.  
  341.             /* Flow files */
  342.  
  343. #ifdef IOS
  344.             if(flo || oft)
  345. #else
  346.             if(flo)
  347. #endif
  348.             {
  349.                 /* indirekte Filelänge/Fileanzahl addieren */ ;
  350.                 sprintf (fname, "%s%s", HoldAreaNameMunge (&(p->mail_addr)), dta.name);
  351.  
  352.                 fp = fopen (fname, "r");    /* was "rb" */
  353.                 if (fp != NULL)
  354.                 {
  355.                     while (!feof (fp))
  356.                     {
  357.                         fname[0] = 0;
  358.                         if (fgets (fname, 79, fp) != NULL)
  359.                         {
  360.                             fnameptr = fname;
  361.  
  362.                             for (i = 0; fnameptr[i]; i++)
  363.                             {
  364.                                 if (fnameptr[i] <= ' ')
  365.                                 {
  366.                                     fnameptr[i] = '\0';
  367.                                 }
  368.                             }
  369.                             /* SWG: 22Aug91 Prevent error with ~:\ */
  370.                             if( !fnameptr[0] || (fnameptr[0] == ';') || (fnameptr[0] == '~'))
  371.                                 continue;
  372.                             if ((fnameptr[0] == TRUNC_AFTER) || (fnameptr[0] == SHOW_DELETE_AFTER))
  373.                             {
  374.                                 fnameptr++;
  375.                             }
  376.  
  377.                             if (stat (fnameptr, &statbuf) == 0)
  378.                             {
  379.                                 p->size += statbuf.st_size;
  380.                                 p->files++;
  381.                             }
  382.                             /* bei MO?/WE? etc indirektes Filedatum ermitteln */ ;
  383.                         }
  384.                     }                                                         /* WHILE */
  385.                     fclose(fp);
  386.                 }                                                 /* ?LO-File found */
  387.             }
  388.  
  389.             if (bad)
  390.             {
  391.                 /* BadCalls hochzählen */ ;
  392.                 sprintf (fname, "%s%s", HoldAreaNameMunge (&(p->mail_addr)), dta.name);
  393.  
  394.                 i = open (fname, O_BINARY|O_RDONLY);
  395.                 (void) read (i, &(p->calls), sizeof (p->calls));
  396.                 (void) close (i);
  397.  
  398.                 p->costcalls += *e3-'0';
  399.                 p->calls += *e3-'0';
  400.             }
  401.         }
  402.     }
  403. }
  404.  
  405. static void extended_xmit_reset (REGIONP zoomwin)
  406. {
  407.     ADDR tmp;
  408.     MAILP p;
  409.     char *domain;
  410.     int k, zone;
  411.  
  412.     p = mail_top;
  413.     while (p != NULL)
  414.     {
  415.         p->calls     = 0;
  416.         p->costcalls = 0;
  417.         p->files     = 0;
  418.         p->size      = 0L;
  419.         p->oldest    = (long) time (NULL);
  420.         p = p->next;
  421.     }
  422.  
  423.     k = 0;
  424.     domain = domain_name[0];
  425.  
  426.     do
  427.     {
  428.         ADDRESS *ad;
  429.         int count, count1;
  430.         int ourzone[ALIAS_CNT];    /* record of our own zones */
  431.         int zonecnt;
  432.  
  433.         /*
  434.          * Do our own zones first
  435.          */
  436.         
  437.         ad = alias;
  438.         count = num_addrs;
  439.         zonecnt = 0;
  440.         while(count--)
  441.         {
  442.             if(!domain || (ad->ad.Domain == domain))
  443.             {
  444.                 /* Check we havnt already done it */
  445.                     
  446.                 count1 = zonecnt;
  447.                 while(count1--)
  448.                 {
  449.                     if(ourzone[count1] == ad->ad.Zone)
  450.                         break;
  451.                 }
  452.                 if(count1 < 0)
  453.                 {
  454.                     extended_dodir(domain, ad->ad.Zone, zoomwin);
  455.                     ourzone[zonecnt++] = ad->ad.Zone;
  456.                 }
  457.             }
  458.             ad++;
  459.         }
  460.  
  461.         if(!no_zones)
  462.         {
  463.             do
  464.             {
  465.                 tmp.Zone = -1;
  466.                 tmp.Domain = domain;
  467.                 tmp.Net = 
  468.                 tmp.Node = 
  469.                 tmp.Point = 0;
  470.             
  471.                 zone = nodefind(&tmp, 0);
  472.                 if(zone > 0)
  473.                 {
  474.                     /* Check we havnt already done it */
  475.                     
  476.                     count = zonecnt;
  477.                     while(count--)
  478.                     {
  479.                         if(ourzone[count] == zone)
  480.                             break;
  481.                     }
  482.                     if(count < 0)
  483.                         extended_dodir(domain, zone, zoomwin);
  484.                 }
  485.             } while(zone > 0);
  486.         }
  487.  
  488.         domain = domain_name[++k];
  489.     }
  490.     while (domain != NULL);
  491. }
  492.  
  493. int Overlay_Do_Zoom (SAVEP rp, int x)
  494. {
  495.     REGIONP zoomwin;
  496.     MAILP p;
  497.     long t_idle;
  498.     int i,c;
  499.     int height;
  500.  
  501.     /* is there something in the outbound ? */
  502.     if (mail_top == NULL)
  503.     {
  504.         status_line (msgtxt[M_NOTHING_IN_OUTBOUND_STATUS]);
  505.         return (0);
  506.     }
  507.  
  508.     /* is there a window */
  509.     if (rp != NULL)
  510.     {
  511.         zoomwin = rp->region;
  512.  
  513.         /* draw a box */
  514.         sb_fill (zoomwin, ' ', colors.hold);
  515.         sb_box (zoomwin, boxtype, (colors.borders ? colors.borders : colors.hold));
  516.  
  517.         /* give it a title */
  518.         sb_move (zoomwin, 0, 1);
  519.         if (colors.headers) sb_wa(zoomwin, colors.headers, 30);
  520.         sb_puts (zoomwin, " Zoomed Pending Outbound Mail ");
  521.  
  522.         /* do we need info ? */
  523.         if (!mail_top->files)
  524.         {
  525.             sb_move (zoomwin, 1, 2);
  526.             sb_puts (zoomwin, "Please wait ...");
  527.             sb_show ();
  528.             extended_xmit_reset (zoomwin);
  529.         }
  530.  
  531.         p = mail_top;
  532.         zoom_window (zoomwin, p);
  533.         height = zoomwin->r1 - zoomwin->r0;
  534.  
  535.         t_idle = timerset(6000);
  536.         while (!timeup (t_idle) && (PEEKBYTE () == -1))
  537.         {
  538.             if (KEYPRESS ())
  539.             {
  540.                 t_idle = timerset(3000);
  541.                 c = (int) FOSSIL_CHAR ();
  542.  
  543.                 if (c == PGUP)
  544.                 {
  545.                     for (i = 2; i < height; i++)
  546.                     {
  547.                         if (p->prev != NULL)
  548.                             p = p->prev;
  549.                     }
  550.                 }
  551.                 else
  552.                 if (c == PGDN)
  553.                 {
  554.                     for (i = 2; i < height; i++)
  555.                     {
  556.                         if (p->next != NULL)
  557.                             p = p->next;
  558.                     }
  559.                 }
  560.                 else
  561.                 if (c == UPAR)
  562.                 {
  563.                     if (p->prev != NULL)
  564.                     {
  565.                         p = p->prev;
  566.                     }
  567.                 }
  568.                 else
  569.                 if (c == DNAR)
  570.                 {
  571.                     if (p->next != NULL)
  572.                     {
  573.                         p = p->next;
  574.                     }
  575.                 }
  576.                 else
  577.                 if (c == HOME)
  578.                 {
  579.                     p = mail_top;
  580.                 }
  581.                 else
  582.                 if (c == END)
  583.                 {
  584.                     while (p->next != NULL)
  585.                         p = p->next;
  586.                     for (i = 2; i < height; i++)
  587.                     {
  588.                         if (p->prev != NULL)
  589.                             p = p->prev;
  590.                     }
  591.                 }
  592.                 else
  593.                 /* ALT-Z, Space, ESCape or Return terminates */
  594.                 if (c == ALTZ)
  595.                     return (x);
  596.  
  597.                 c &= 0x00ff;
  598.  
  599.                 if ((c == 0x20) || (c == 0x1b) || (c == 0x0d))
  600.                     return (x);
  601.  
  602.                 if (!KEYPRESS ())
  603.                     zoom_window (zoomwin, p);
  604.  
  605.             }
  606.         }
  607.     }
  608.     /* return value is never checked, just use x so lint and -w3 don't get mad */
  609.     return (x);
  610. }
  611.  
  612.  
  613.  
  614. /*
  615.  * Find mail for an address in the MAILP list
  616.  */
  617.  
  618. MAILP find_mail( ADDR *address )
  619. {
  620.     MAILP p;
  621.  
  622.     p = mail_top;
  623.     while (p != NULL)
  624.     {
  625.         if ((no_zones || (p->mail_addr.Zone == address->Zone)) &&
  626.             (p->mail_addr.Net == address->Net) &&
  627.             (p->mail_addr.Node == address->Node) &&
  628.             (p->mail_addr.Point == address->Point) &&
  629.             ((p->mail_addr.Domain == address->Domain) ||
  630.             ((p->mail_addr.Domain == alias[0].ad.Domain) &&
  631.             (address->Domain == NULL))))
  632.             break;
  633.         p = p->next;
  634.     }
  635.  
  636.     return (p);
  637. }
  638.  
  639. /*
  640.  * Fill in data into MAILP node
  641.  *
  642.  * uses dta_str, which is the DTA area for a recently found file
  643.  *
  644.  * returns 1 for an error or node already exists in list
  645.  */
  646.  
  647. static int xmit_install (MAILP p, int zone, char *domain)
  648. {
  649.     MAILP p1, p2;
  650.     int rettype;
  651.     ADDR tmp;
  652. #ifdef IOS
  653.     char *s;
  654. #endif
  655.     
  656. #ifdef IBMC
  657.     char tnet[5], tnode[5];
  658. #endif
  659.  
  660.  
  661.     /* Interpret the net/node from the filename */
  662.  
  663.     tmp.Zone = zone;        /* Set up defaults */
  664.     tmp.Domain = domain;
  665.  
  666. #ifdef IOS
  667.     s = strchr(dta_str.name, '.');
  668.     
  669.     if(s && (s[2] != 'U') && (s[3] == 'T'))
  670.         getaddress(dta_str.name, &tmp.Net, &tmp.Node, &tmp.Point);
  671.     else
  672. #endif
  673.         if(get2daddress(dta_str.name, &tmp) == FALSE)
  674.             return 1;
  675.      
  676.     p2 = find_mail (&tmp);
  677.     if (p2 == NULL)
  678.     {
  679.         /* We didn't find it in what we have already */
  680.         p1 = p;
  681.         p1->mail_addr.Zone = tmp.Zone;
  682.         p1->mail_addr.Net = tmp.Net;
  683.         p1->mail_addr.Node = tmp.Node;
  684.         p1->mail_addr.Point = tmp.Point;
  685.         p1->mail_addr.Domain = tmp.Domain;
  686.         rettype = 0;
  687.     }
  688.     else
  689.     {
  690.         /* We found it, so we have to make sure the higher level routine knows */
  691.         p1 = p2;
  692.         rettype = 1;
  693.     }
  694.  
  695.     switch (dta_str.name[9])
  696.     {
  697.     case 'C':              /* Crash */
  698.         p1->mailtypes |= MAIL_CRASH;
  699.         break;
  700.  
  701.     case 'H':              /* Hold */
  702.         p1->mailtypes |= MAIL_HOLD;
  703.         break;
  704.  
  705.     case 'F':              /* Normal */
  706.     case 'O':
  707.         p1->mailtypes |= MAIL_NORMAL;
  708.         break;
  709.  
  710.     case 'D':              /* Direct */
  711.         p1->mailtypes |= MAIL_DIRECT;
  712.         break;
  713.  
  714.     case 'R':              /* Request */
  715.         p1->mailtypes |= MAIL_REQUEST;
  716.         break;
  717.     }
  718. #ifdef IOS
  719.     if(dta_str.name[10] == 'R')
  720.         p1->mailtypes |= MAIL_REQUEST;
  721. #endif
  722.  
  723.     /* SWG: 11Jul91 : Speed up reading */
  724.     /* Avoid nodelist check if already processed this address! */
  725.  
  726.     if(p2)
  727.     {
  728.         if(p1->mailtypes & MAIL_UNKNOWN)
  729.             return rettype;
  730.     }
  731.     else
  732.     {
  733.         if (!nodefind (&(p1->mail_addr), 0))
  734.         {
  735.             p1->mailtypes |= MAIL_UNKNOWN;
  736.             return (rettype);
  737.         }
  738.         p1->realcost = newnodedes.RealCost;
  739.         p1->nodeflags = newnodedes.NodeFlags;
  740.     }
  741.  
  742.  
  743.     /* REQUEST  03.08.1990 */
  744.     /* Don't call for "HOLD" stuff. */
  745.     if (dta_str.name[9] == 'H')
  746.     {
  747.         return (rettype);
  748.     }
  749.  
  750.     /* Don't call for "REQ" stuff if not allowed */
  751. #ifdef IOS
  752.     if (!requests_ok && ((dta_str.name[9] == 'R') || (dta_str.name[10] == 'R')))
  753. #else
  754.     if ((dta_str.name[9] == 'R') && (!requests_ok))
  755. #endif
  756.     {
  757.         return (rettype);
  758.     }
  759.  
  760.     /* If there's no event, set mail to 'go' */
  761.  
  762.     if (cur_event < 0)
  763.     {
  764.         p1->mailtypes |= MAIL_WILLGO;
  765.         return (rettype);
  766.     }
  767.  
  768.     /* if mail is direct, set mail to 'go'    */
  769.     
  770.     if (dta_str.name[9] == 'D')
  771.     {
  772.         p1->mailtypes |= MAIL_WILLGO;
  773.         return (rettype);
  774.     }
  775.         
  776.     /* REQUEST  22.08.1990 */
  777.     /* If it is not supposed to be outbound requests, go on */
  778.     if ((e_ptrs[cur_event]->behavior & MAT_NOOUTREQ) &&
  779. #ifdef IOS
  780.         ((dta_str.name[10] == 'R') || (dta_str.name[9] == 'R')))
  781. #else
  782.         (dta_str.name[9] == 'R'))
  783. #endif
  784.     {
  785.         return (rettype);
  786.     }
  787.  
  788.     /* If it is a crash only event and this wasn't crash, return */
  789.     if ((dta_str.name[9] != 'C') && (e_ptrs[cur_event]->behavior & MAT_CM))
  790.     {
  791.         return (rettype);
  792.     }
  793.  
  794.     /*
  795.     ** Check for costs. If UseCallSlots is set, then take them instead
  796.     */
  797.     
  798.     if (usecallslots)
  799.     {
  800.         /*
  801.         ** check if slot exits, don't call for CRASH mail waiting
  802.         ** for other nodes if slot is not found
  803.         */
  804.         
  805.         s = strchr (e_ptrs[cur_event]->call_slot, (int)p1->realcost);
  806.         if (!s || !*s)
  807.         {
  808.             /*
  809.             ** no slot for node!!
  810.             ** Did we have slots for this event ?
  811.             ** Then don't call if mail is crash
  812.             **/
  813.             
  814.             if (e_ptrs[cur_event]->call_slot[0])
  815.             {
  816.                 if (dta_str.name[9] != 'C') 
  817.                 {
  818.                     return (rettype);
  819.                 }
  820.                 else
  821.                 {
  822.                     if (!(e_ptrs[cur_event]->behavior & MAT_CM)) return (rettype);
  823.                 }
  824.             }
  825.         }
  826.     }
  827.     else
  828.     {
  829.         /* Is this a local only event? */
  830.         if (e_ptrs[cur_event]->behavior & MAT_LOCAL)
  831.         {
  832.             /*
  833.             ** If this is supposed to be only local, then get out if it isn't 
  834.             */
  835.             if (e_ptrs[cur_event]->node_cost >= 0)
  836.             {
  837.                 if ((int) p1->realcost > e_ptrs[cur_event]->node_cost)
  838.                 {
  839.                     return (rettype);
  840.                 }
  841.             }
  842.             else
  843.             {
  844.                 if ((int) p1->realcost < -e_ptrs[cur_event]->node_cost)
  845.                 {
  846.                     return (rettype);
  847.                 }
  848.             }
  849.         }
  850.     }
  851.  
  852.     /* Is this a non-mail window event? */
  853. #ifndef ATARIST
  854.     if (newnodelist && (!(e_ptrs[cur_event]->behavior & MAT_NOMAIL24)))
  855. #else
  856.     if (!(e_ptrs[cur_event]->behavior & MAT_NOMAIL24))
  857. #endif
  858.     {
  859.         /* If this guy can't handle crash, get out and try again */
  860.         if (!(p1->nodeflags & B_CM) && (!s || !*s))
  861.         {
  862.             return (rettype);
  863.         }
  864.     }
  865.  
  866.     /* Is this a receive only event? */
  867.     if (e_ptrs[cur_event]->behavior & MAT_NOOUT)
  868.     {
  869.         return (rettype);
  870.     }
  871.  
  872.     /* Is this a non-CM event? */
  873. #ifndef ATARIST
  874.     if (newnodelist && (e_ptrs[cur_event]->behavior & MAT_NOCM) &&
  875.         (p1->nodeflags & B_CM))
  876. #else
  877.     if((e_ptrs[cur_event]->behavior & MAT_NOCM) && (p1->nodeflags & B_CM))
  878. #endif
  879.     {
  880.         return (rettype);
  881.     }
  882.  
  883.     /* See if we spent too much calling him already */
  884.     if (bad_call (&(p1->mail_addr), BAD_STATUS))
  885.     {
  886.         p1->mailtypes |= MAIL_TOOBAD;
  887.         return (rettype);
  888.     }
  889.  
  890.     p1->mailtypes |= MAIL_WILLGO;
  891.  
  892.     return (rettype);
  893. }
  894.  
  895.  
  896.  
  897. void xmit_window( MAILP p1 )
  898. {
  899.     MAILP p;
  900.     int i;
  901.     char node_str[16];            /* for zz:nnnnn:nnnnn */
  902.     char domain_str[9];               /* for the domain or files/size/age */
  903.     char flag_str[7];             /* for the flags */
  904.     char size_str[6];             /* for Bytes, kBytes or MBytes */
  905.     char *res_str;
  906.     int n;                        /* counter */
  907.     char j1[40];
  908.  
  909.     if (!fullscreen)
  910.         return;
  911.  
  912.     /*
  913.      * SWG: Default to mail_top and set next_mail
  914.      */
  915.     
  916.     if(p1 == NULL)
  917.         p1 = mail_top;
  918. #if 0
  919.     if(next_mail == NULL)
  920.         next_mail = p1;
  921. #endif
  922.  
  923.     p = p1;
  924.  
  925.     sb_fillc (holdwin, ' ');
  926.  
  927.     if (p == NULL)
  928.     {
  929.         sb_move (holdwin, 3, 5);
  930.         sb_puts (holdwin, (unsigned char *) msgtxt[M_NOTHING_IN_OUTBOUND]);
  931.         return;
  932.     }
  933.  
  934.     if (niceoutbound)
  935.     {
  936.         sb_move (holdwin, 1, 1);
  937.         sb_puts (holdwin, "Node      Files Size Age Status");
  938.     }
  939.     else
  940.     {
  941.         sb_move (holdwin, 1, 2);
  942.         sb_puts (holdwin, (unsigned char *) msgtxt[M_OUTBOUND_HEADER]);
  943.     }
  944.  
  945.     for (i = 2; i < 6; i++)
  946.     {
  947.         if (p == NULL)
  948.             break;
  949.  
  950.         sb_move (holdwin, i, 2);
  951.         /* create formatted address */
  952.         sprintf (node_str, "%u:%u/%u",
  953.                 p->mail_addr.Zone,
  954.                 p->mail_addr.Net,
  955.                 p->mail_addr.Node);
  956.  
  957.         if(p->mail_addr.Point)
  958.             sprintf(&node_str[strlen(node_str)], ".%u", p->mail_addr.Point);
  959.  
  960.         /* create formatted flags */
  961.         if (p->mailtypes & MAIL_UNKNOWN)
  962.             sprintf (flag_str, "Unknwn");
  963.         else
  964.             if (p->mailtypes & MAIL_TOOBAD)
  965.                 sprintf (flag_str, "NoConn");
  966.             else
  967.                 if (p->mailtypes & MAIL_TRIED)
  968.                     sprintf (flag_str, "Tried ");
  969.                 else
  970.                 {
  971.                     n = 0;
  972.                     if (  p->mailtypes & MAIL_HOLD    ) flag_str[n++] = 'H';
  973.                     if (  p->mailtypes & MAIL_NORMAL  ) flag_str[n++] = 'N';
  974.                     if (  p->mailtypes & MAIL_CRASH   ) flag_str[n++] = 'C';
  975.                     if (  p->mailtypes & MAIL_DIRECT  ) flag_str[n++] = 'D';
  976.                     if (  p->mailtypes & MAIL_REQUEST ) flag_str[n++] = 'R';
  977.                     if (!(p->mailtypes & MAIL_WILLGO )) flag_str[n++] = '-';
  978.                     flag_str[n] = '\0';
  979.                 }
  980.  
  981.         if (niceoutbound)
  982.         {
  983.             /* create extra info */
  984.             if (p->size > 10238976L)
  985.                 sprintf (size_str, "%4ulM", (p->size+1048575L)/1048576L);
  986.             else
  987.                 if (p->size > 9999)
  988.                     sprintf (size_str, "%4luk", (p->size+1023)/1024);
  989.                 else
  990.                     sprintf (size_str, "%4lu ",  p->size);
  991.             n = (int) ( ((long)time(NULL) - p->oldest) / 86400L );
  992.             sb_move (holdwin, i, 1);
  993.             sprintf (j1, "%-12.12s%3u%6s%3u%7s",
  994.                 node_str, p->files, size_str, (n > 999) ? 999 : n, flag_str);
  995.         }
  996.         else
  997.         {
  998.             /* create formatted domain if any */
  999.             if(p->mail_addr.Domain == NULL)
  1000.                 strcpy (domain_str, "FidoNet");
  1001.             else
  1002.             {
  1003.                 strncpy (domain_str, p->mail_addr.Domain, 8);
  1004.                 res_str = strchr (domain_str, '.');
  1005.                 if (res_str != NULL)
  1006.                     *res_str = '\0';
  1007.                 domain_str[8] = '\0';
  1008.             }
  1009.             sb_move (holdwin, i, 2);
  1010.             sprintf (j1, "%-15s%-8s%6s", node_str, domain_str, flag_str);
  1011.         }
  1012.         sb_puts (holdwin, (unsigned char *) j1);
  1013.         p = p->next;
  1014.     }
  1015.  
  1016.     sb_show ();
  1017. }
  1018.  
  1019. /*
  1020.  * Sort the outbound mail
  1021.  */
  1022.  
  1023. static void xmit_sort (void)
  1024. {
  1025.     MAILP p, p1, p2;
  1026.  
  1027.     do_ready ("Sorting");
  1028.  
  1029.     p1 = mail_top;
  1030.     while (p1 != NULL)
  1031.     {
  1032.         p2 = p1->next;
  1033.         while (p2 != NULL)
  1034.         {
  1035.             if(      (p2->mail_addr.Zone  < p1->mail_addr.Zone )
  1036.                 || ( (p2->mail_addr.Zone == p1->mail_addr.Zone ) &&
  1037.                    ( (p2->mail_addr.Net   < p1->mail_addr.Net  )
  1038.                 || ( (p2->mail_addr.Net  == p1->mail_addr.Net  ) &&
  1039.                    ( (p2->mail_addr.Node  < p1->mail_addr.Node )
  1040.                 || ( (p2->mail_addr.Node == p1->mail_addr.Node ) &&
  1041.                      (p2->mail_addr.Point < p1->mail_addr.Point) ))))))
  1042.             {
  1043.  
  1044.                 /* p2 ausklinken */
  1045.                 p2->prev->next = p2->next;
  1046.                 if (p2->next != NULL) p2->next->prev = p2->prev;
  1047.  
  1048.                 /* p2 vor p1 einklinken */
  1049.                 p2->prev = p1->prev;
  1050.                 if (p2->prev != NULL) p2->prev->next = p2;
  1051.                 p2->next = p1;
  1052.                 p1->prev = p2;
  1053.  
  1054.                 /* korrigieren */
  1055.                 if (p1 == mail_top) mail_top = p2;
  1056.                 p = p2;
  1057.                 p2 = p1;
  1058.                 p1 = p;
  1059.             }
  1060.             p2 = p2->next;
  1061.         }
  1062.         p1 = p1->next;
  1063.     }
  1064.     p = mail_top;
  1065.  
  1066.     /* Find the first that is sendable */
  1067.     while (p != NULL)
  1068.     {
  1069.         if ((p->mailtypes & MAIL_WILLGO) &&
  1070.             (!(p->mailtypes & MAIL_TOOBAD)) &&
  1071.             (!(p->mailtypes & MAIL_UNKNOWN)))
  1072.             break;
  1073.         p = p->next;
  1074.     }
  1075.  
  1076.     if (p == NULL)
  1077.         return;
  1078.  
  1079.     /* Put the first sendable one on top */
  1080.     if (p != mail_top)
  1081.     {
  1082.         p->prev->next = p->next;
  1083.         if (p->next != NULL)
  1084.             p->next->prev = p->prev;
  1085.         p->prev = NULL;
  1086.         p->next = mail_top;
  1087.         mail_top->prev = p;
  1088.         mail_top = p;
  1089.     }
  1090.  
  1091.     p1 = p;
  1092.     p = p1->next;
  1093.     while (p != NULL)
  1094.     {
  1095.         if ((p->mailtypes & MAIL_WILLGO) &&
  1096.             (!(p->mailtypes & MAIL_TOOBAD)) &&
  1097.             (!(p->mailtypes & MAIL_UNKNOWN)))
  1098.         {
  1099.             if (p->prev == p1)
  1100.             {
  1101.                 p1 = p;
  1102.                 p = p->next;
  1103.                 continue;
  1104.             }
  1105.             p2 = p->next;
  1106.             p->prev->next = p->next;
  1107.             if (p->next != NULL)
  1108.                 p->next->prev = p->prev;
  1109.             p->next = p1->next;
  1110.             if (p1->next != NULL)
  1111.                 p1->next->prev = p;
  1112.             p->prev = p1;
  1113.             p1->next = p;
  1114.             p1 = p;
  1115.             p = p2;
  1116.         }
  1117.         else
  1118.         {
  1119.             p = p->next;
  1120.         }
  1121.     }
  1122. }
  1123.  
  1124. /*
  1125.  * Read mail from a directory
  1126.  */
  1127.  
  1128. static void do_dir(char *domain, int zone, MAILP *pp)
  1129. {
  1130.     ADDR tmp;
  1131.     MAILP p = *pp;
  1132. #if (!defined(OS_2) && !defined(LATTICE))
  1133.     int j;
  1134. #endif
  1135.     char *holdpath;
  1136. #ifdef NEW
  1137.     struct stat buffer;
  1138. #endif
  1139.  
  1140.  
  1141. #ifdef NEW
  1142.     if(fullscreen)
  1143.     {
  1144.         char s[16];
  1145.  
  1146.         sb_fillc (holdwin, ' ');
  1147.         if(domain)
  1148.         {
  1149.             sb_move(holdwin, 2, 4);
  1150.             sb_puts(holdwin, "Domain: ");
  1151.             sb_puts(holdwin, domain);
  1152.         }
  1153.         sb_move(holdwin, 3, 6);
  1154.         sb_puts(holdwin, "Zone: ");
  1155.         sprintf(s, "%d", zone);
  1156.         sb_puts(holdwin, s);
  1157.         sb_show();
  1158.     }
  1159. #endif
  1160.  
  1161.     tmp.Zone = zone;
  1162.     tmp.Net = 
  1163.     tmp.Node = 
  1164.     tmp.Point = 0;
  1165.     tmp.Domain = domain;
  1166.     holdpath = HoldAreaNameMunge(&tmp);
  1167. #ifdef NEW
  1168.  
  1169.     /* Check if folder exists and create if neccessary */
  1170.  
  1171.     strcpy(next_one, holdpath);
  1172.     next_one[strlen(next_one) -1] = 0;
  1173.     if(stat(next_one, &buffer))
  1174.     {
  1175.         if(mkdir(next_one) == 0)
  1176.             status_line(msgtxt[M_CREATED_DIR], next_one);
  1177.         else
  1178.         {
  1179.             status_line(msgtxt[M_BAD_DIR], next_one);
  1180.             status_line(msgtxt[M_NO_CREATE_DIR]);
  1181.             return;
  1182.         }
  1183.     }
  1184.         
  1185. #endif
  1186.     sprintf (next_one, "%s*.*", holdpath);
  1187.  
  1188.  
  1189. #if (!defined(OS_2) && !defined(LATTICE))
  1190.     j = 0;
  1191. #endif
  1192.  
  1193. #if defined(OS_2)
  1194.         if(!dir_findfirsta(next_one, _A_NORMAL, &dta_str))
  1195. #else
  1196.         if(!dfind(&dta_str, next_one, 0))
  1197. #endif
  1198.         do
  1199.         {
  1200.           char *ext = strchr(dta_str.name, '.');
  1201.           if(ext)
  1202.           {
  1203.             ext++;
  1204.  
  1205. #ifdef IOS
  1206.             if( ext[0] && ext[1] && ext[2] &&
  1207.                ((            strchr("APFRU", ext[1]) && (ext[2] == 'T') ) ||
  1208.                 (                    (ext[1] == 'L') && (ext[2] == 'O') ) ||
  1209.                 ( (ext[0] == 'R') && (ext[1] == 'E') && (ext[2] == 'Q') ) ) )
  1210. #else
  1211.             if( (                    (ext[1] == 'U') && (ext[2] == 'T') ) ||
  1212.                 (                    (ext[1] == 'L') && (ext[2] == 'O') ) ||
  1213.                 ( (ext[0] == 'R') && (ext[1] == 'E') && (ext[2] == 'Q') ) )
  1214. #endif
  1215.             {
  1216.                 /* We found a name, remember it */
  1217.                 if (p == NULL)
  1218.                     p = mail_top = (MAILP) calloc (sizeof (MAIL), 1);
  1219.                 else
  1220.                 {
  1221.                     p->next = (MAILP) calloc (sizeof (MAIL), 1);
  1222.                     p->next->prev = p;
  1223.                     p = p->next;
  1224.                 }
  1225.  
  1226.                 if (xmit_install (p, zone, domain))
  1227.                 {
  1228.                     /* No good */
  1229.                     if (p->prev != NULL)
  1230.                     {
  1231.                         p = p->prev;
  1232.                         free (p->next);
  1233.                         p->next = NULL;
  1234.                     }
  1235.                     else
  1236.                     {
  1237.                         free (p);
  1238.                         p = mail_top = NULL;
  1239.                     }
  1240.                 }
  1241.             }
  1242.             }
  1243.  
  1244. #if (!defined(OS_2) && !defined(LATTICE))
  1245.             ++j;
  1246. #endif
  1247.         }
  1248. #if defined(OS_2)
  1249.         while(!dir_findnexta(&dta_str));
  1250. #elif defined(LATTICE)
  1251.         while(!dnext(&dta_str));                        /* got one */
  1252. #else
  1253.         while(!dfind(&dta_str, next_one, j));
  1254. #endif
  1255.  
  1256.     *pp = p;
  1257. }
  1258.  
  1259.  
  1260. /*
  1261.  * Reset the outbound mail structures
  1262.  */
  1263.  
  1264. void xmit_reset( void )
  1265. {
  1266.     MAILP p;
  1267.     int k, zone;
  1268.     char *domain;
  1269.     ADDR tmp;
  1270.  
  1271.     readhold_ctr = readhold_time;
  1272.  
  1273.     do_ready ("Reading");
  1274.  
  1275.     /* First get rid of all the old junk */
  1276.  
  1277.     p = mail_top;
  1278.     if (p != NULL)
  1279.     {
  1280.         while (p->next != NULL)                /* Get to end of list */
  1281.             p = p->next;
  1282.         while (p->prev != NULL)                /* Work back through list freeing memory */
  1283.         {
  1284.             p = p->prev;
  1285.             free (p->next);
  1286.         }
  1287.         if (p != NULL)
  1288.             free (p);
  1289.     }
  1290.  
  1291.     p = mail_top = NULL;
  1292.  
  1293.     k = 0;
  1294.     domain = domain_name[0];
  1295.  
  1296.     /* For each Domain */
  1297.  
  1298.     do
  1299.     {
  1300.         /* For each Zone */
  1301.  
  1302.         ADDRESS *ad;
  1303.         int count, count1;
  1304.         int ourzone[ALIAS_CNT];    /* record of our own zones */
  1305.         int zonecnt;
  1306.  
  1307.         lock_nodelist(TRUE);        /* Keep nodelist file open */
  1308.  
  1309.         /*
  1310.          * Do our own zones first
  1311.          */
  1312.         
  1313.         ad = alias;
  1314.         count = num_addrs;
  1315.         zonecnt = 0;
  1316.         while(count--)
  1317.         {
  1318.             if(!domain || (ad->ad.Domain == domain))
  1319.             {
  1320.                 /* Check we havnt already done it */
  1321.                     
  1322.                 count1 = zonecnt;
  1323.                 while(count1--)
  1324.                 {
  1325.                     if(ourzone[count1] == ad->ad.Zone)
  1326.                         break;
  1327.                 }
  1328.                 if(count1 < 0)
  1329.                 {
  1330.                     do_dir(domain, ad->ad.Zone, &p);
  1331.                     ourzone[zonecnt++] = ad->ad.Zone;
  1332.                 }
  1333.             }
  1334.             ad++;
  1335.         }
  1336.  
  1337.         if(!no_zones)
  1338.         {
  1339.             do
  1340.             {
  1341.                 tmp.Zone = -1;
  1342.                 tmp.Domain = domain;
  1343.                 tmp.Net = 
  1344.                 tmp.Node = 
  1345.                 tmp.Point = 0;
  1346.             
  1347.                 zone = nodefind(&tmp, 0);
  1348.                 if(zone > 0)
  1349.                 {
  1350.                     /* Check we havnt already done it */
  1351.                     
  1352.                     count = zonecnt;
  1353.                     while(count--)
  1354.                     {
  1355.                         if(ourzone[count] == zone)
  1356.                             break;
  1357.                     }
  1358.                     if(count < 0)
  1359.                         do_dir(domain, zone, &p);
  1360.                 }
  1361.             } while(zone > 0);
  1362.         }
  1363.  
  1364.         lock_nodelist(FALSE);        /* Unlock nodelist */
  1365.  
  1366.         domain = domain_name[++k];
  1367.  
  1368.     } 
  1369.     while (domain != NULL);
  1370.  
  1371.     next_mail = NULL;
  1372.  
  1373.     xmit_sort ();
  1374.  
  1375.     if (niceoutbound)
  1376.         extended_xmit_reset (NULL);
  1377.  
  1378.     xmit_window (mail_top);
  1379.  
  1380.     do_ready (msgtxt[M_READY_WAITING]);
  1381. }
  1382.  
  1383. int xmit_next( ADDR *xaddr )
  1384. {
  1385.     /* Set up the proper pointer */
  1386.     if ((next_mail == NULL) || (next_mail->next == NULL))
  1387.         next_mail = mail_top;
  1388.     else
  1389.         next_mail = next_mail->next;
  1390.  
  1391.     /* Loop through till we find something we can send */
  1392.     while (next_mail != NULL)
  1393.     {
  1394.         if ((next_mail->mailtypes & MAIL_WILLGO) &&
  1395.             (!(next_mail->mailtypes & MAIL_UNKNOWN)) &&
  1396.             (!(next_mail->mailtypes & MAIL_TOOBAD)))
  1397.         {
  1398.             if (bad_call (&(next_mail->mail_addr), BAD_STATUS))
  1399.             {
  1400.                 next_mail->mailtypes |= MAIL_TOOBAD;
  1401.             }
  1402.             else
  1403.             {
  1404.                 xaddr->Zone = next_mail->mail_addr.Zone;
  1405.                 xaddr->Net = next_mail->mail_addr.Net;
  1406.                 xaddr->Node = next_mail->mail_addr.Node;
  1407.                 xaddr->Point = next_mail->mail_addr.Point;
  1408.                 xaddr->Domain = next_mail->mail_addr.Domain;
  1409.                 xmit_window (next_mail);
  1410.                 return (1);
  1411.             }
  1412.         }
  1413.         next_mail = next_mail->next;
  1414.     }
  1415.  
  1416.     /* Read the disk again since we reached the end of the list */
  1417. #ifdef OS_2
  1418.     xmit_reset ();
  1419. #endif
  1420.  
  1421.     next_mail = mail_top;
  1422.  
  1423.     /* Try the new list and see what happens */
  1424.     while (next_mail != NULL)
  1425.         {
  1426.         if ((next_mail->mailtypes & MAIL_WILLGO) &&
  1427.             (!(next_mail->mailtypes & MAIL_UNKNOWN)) &&
  1428.             (!(next_mail->mailtypes & MAIL_TOOBAD)))
  1429.             {
  1430.             if (bad_call (&(next_mail->mail_addr), BAD_STATUS))
  1431.                 {
  1432.                 next_mail->mailtypes |= MAIL_TOOBAD;
  1433.             }
  1434.             else
  1435.             {
  1436.                 xaddr->Zone = next_mail->mail_addr.Zone;
  1437.                 xaddr->Net = next_mail->mail_addr.Net;
  1438.                 xaddr->Node = next_mail->mail_addr.Node;
  1439.                 xaddr->Point = next_mail->mail_addr.Point;
  1440.                 xaddr->Domain = next_mail->mail_addr.Domain;
  1441.                 xmit_window (next_mail);
  1442.                 return (1);
  1443.             }
  1444.         }
  1445.         next_mail = next_mail->next;
  1446.     }
  1447.  
  1448.     /* Oh well, we tried */
  1449.     xmit_window (mail_top);
  1450.     return (0);
  1451. }
  1452.  
  1453.  
  1454. /*
  1455.  * Handle Bad call files (*.$$?)
  1456.  *
  1457.  * baddr : Address
  1458.  *   rwd : a flag:
  1459.  *        0 = BAD_STATUS    = Get status for address (0=OK to call, 1=made too many calls)
  1460.  *        1 = BAD_CARRIER   = Mark bad call with carrier
  1461.  *        2 = BAD_NOCARRIER = Mark bad call without carrier
  1462.  *      3 = BAD_STOPCALL  = Mark as uncallable
  1463.  *      -ve = BAD_REMOVE    = Remove old bad files
  1464.  */
  1465.  
  1466. int bad_call( ADDR *baddr, int rwd )
  1467. {
  1468.     int res;
  1469.     int i, j;
  1470.     struct FILEINFO bad_dta;
  1471.     FILE *bad_wazoo;
  1472.     char *p;
  1473.     char *HoldName;
  1474.     char fname[80];
  1475.     char fname1[80];
  1476.  
  1477. #ifdef DEBUG
  1478.     status_line(">update_$$?(%s,%d)", Pretty_Addr_Str(baddr), rwd);
  1479. #endif
  1480.  
  1481.     HoldName = HoldAreaNameMunge(baddr);
  1482. #ifdef IOS
  1483.     if(iosmode)
  1484.         sprintf (fname, "%s%s.$$?", HoldName, Addr36(baddr));
  1485.     else
  1486. #endif
  1487.         sprintf (fname, "%s%s.$$?", HoldName, Hex_Addr_Str (baddr));
  1488.     j = (int) strlen (fname) - 1;                           /* Point at ?          */
  1489.     res = -1;                                         /* Initialize to fail  */
  1490.  
  1491.     i = 0;                                            /* This says findfirst */
  1492. #ifdef LATTICE
  1493.     while( i ? !dnext(&bad_dta) : !dfind(&bad_dta, fname, 0))
  1494. #else
  1495.     while (!dfind (&bad_dta, fname, i))                   /* as long as we match */
  1496. #endif
  1497.     {
  1498.         if (isdigit (bad_dta.name[11]))                        /* is there a digit?   */
  1499.         {
  1500.             fname[j] = bad_dta.name[11];                        /* Yes, copy to fname  */
  1501.             res = fname[j] - '0';                               /* Save it for testing */
  1502.             break;                                              /* Get out of while    */
  1503.         }
  1504.         else i = 1;                                        /* Else use findnext   */
  1505.     }
  1506.  
  1507.     if (res == -1)                                        /* Successful search?  */
  1508.     {
  1509.         fname[j] = '0';                                    /* No, base digit = 0  */
  1510.     }
  1511.  
  1512.     if (rwd > 0)
  1513.     {
  1514.         /* Writing a bad call  */
  1515.  
  1516.         /* First create a filename that is one higher than what we've got */
  1517.  
  1518.         (void) strcpy (fname1, fname);
  1519.         fname1[j]++;
  1520.         if (fname1[j] > '9')
  1521.             fname1[j] = '9';
  1522.  
  1523.         if(res == 3)        /* Mark as uncallable */
  1524.             fname1[j] = '9';
  1525.  
  1526.         if (res == -1)                                   /* Did we have a file? */
  1527.         {                                               /* No, make one.       */
  1528.             if (rwd == BAD_NOCARRIER)                  /* No carrier */
  1529.                 res = open (fname, O_CREAT|O_WRONLY|O_BINARY, DEFAULT_MODE);
  1530.             else             /* With carrier */
  1531.                 res = open (fname1, O_CREAT|O_WRONLY|O_BINARY, DEFAULT_MODE);
  1532.             i = rwd - 1;                                /* zero-based count    */
  1533.             write (res, &i, sizeof (int));                /* write it out        */
  1534.             close (res);                                /* close the file      */
  1535.         }
  1536.         else
  1537.         {                                                   /* There was a file    */
  1538.  
  1539.             /*
  1540.                * 2 = Unsuccessful, No carrier. Update contents of the file.
  1541.              */
  1542.  
  1543.             if (rwd == BAD_NOCARRIER)
  1544.             {
  1545.                 i = open (fname, O_RDONLY|O_BINARY);
  1546.                 (void) read (i, (char *) &res, sizeof (int));
  1547.                 (void) close (i);
  1548.  
  1549.                 ++res;
  1550.  
  1551.                 i = open (fname, O_CREAT|O_WRONLY|O_BINARY, DEFAULT_MODE);
  1552.                 (void) write (i, (char *) &res, sizeof (int));
  1553.                 (void) close (i);
  1554.             }
  1555.  
  1556.             /*
  1557.               * 1 or 3 = Unsuccessful, Carrier. Update file name to reflect the
  1558.               * failure.
  1559.              */
  1560.  
  1561.             else
  1562.             {
  1563.                 (void) rename (fname, fname1);
  1564.             }
  1565.         }
  1566.     }
  1567.     else if (rwd == BAD_STATUS)
  1568.     {
  1569.  
  1570.         /*
  1571.            * 0 = We are reading a bad call status
  1572.          */
  1573.  
  1574.         /* Is it automatically ok (no .$$ file there) ? */
  1575.         if (res == -1)
  1576.             return (0);
  1577.  
  1578.         /* Were there too many connects with carrier? */
  1579.         if (res >= max_connects)
  1580.             return (1);
  1581.  
  1582.         /* Ok, check for connects without carrier */
  1583.         res = 0;
  1584.         i = open (fname, O_RDONLY|O_BINARY);
  1585.         (void) read (i, (char *) &res, sizeof (int));
  1586.         (void) close (i);
  1587.         return (res >= max_noconnects);
  1588.     }
  1589.     else
  1590.     {
  1591.  
  1592.         /*
  1593.            * -1 = Cleanup of bad call status. This happens in two steps:
  1594.            * a) delete 'netnode.$$?' in hold area;
  1595.            * b) if a 'netnode.Z' file exists in hold area,
  1596.            *    1) delete all BADWAZOO.xxx files listed in the .Z file;
  1597.            *    2) delete the 'netnode.z' file.
  1598.          */
  1599.  
  1600.         if (res != -1)
  1601.         {
  1602.             (void) unlink (fname);
  1603.         }
  1604.  
  1605.         if (!mail_finished)
  1606.             return (0);
  1607.  
  1608. #ifdef IOS
  1609.         if(iosmode)
  1610.             sprintf (fname, "%s%s.Z", HoldName, Addr36(baddr));
  1611.         else
  1612. #endif
  1613.             sprintf (fname, "%s%s.Z", HoldName, Hex_Addr_Str (baddr));
  1614.         if (dexists (fname))
  1615.         {
  1616.             if ((bad_wazoo = fopen (fname, read_ascii)) == NULL)
  1617.             {
  1618.                 (void) got_error (msgtxt[M_OPEN_MSG], fname);
  1619.             }
  1620.             else
  1621.             {
  1622.                 while (!feof (bad_wazoo))
  1623.                 {
  1624.                     e_input[0] = '\0';
  1625.                     if (!fgets (e_input, 64, bad_wazoo))
  1626.                         break;
  1627.                     /* Point to BADWAZOO.xxx */
  1628.                     p = strchr (e_input, ' ') + 1;
  1629.                     /* Then just past it and terminate */
  1630.                     p = strchr (p, ' ');
  1631.                     *p = '\0';
  1632.                     /* Back to where we were */
  1633.                     p = strchr (e_input, ' ') + 1;
  1634.  
  1635.                     /* Build file name and delete file */
  1636.                     (void) strcpy (fname1, CurrentNetFiles);
  1637.                     (void) strcat (fname1, p);
  1638.                     (void) unlink (fname1);
  1639.                 }
  1640.                 (void) fclose (bad_wazoo);
  1641.             }
  1642.             (void) unlink (fname);
  1643.         }
  1644.     }
  1645.     return (0);
  1646. }
  1647.  
  1648. /*
  1649.  * Kill all BAD $$ files
  1650.  *
  1651.  * Return number of files killed
  1652.  */
  1653.  
  1654. static int kill_badzone(ADDR *ad)
  1655. {
  1656.     int flag = 0;
  1657.     char *folder = HoldAreaNameMunge(ad);
  1658.  
  1659.  
  1660.     sprintf (next_one, "%s*.$$?", folder);
  1661.  
  1662. #ifdef DEBUG
  1663.     status_line(">Deleting %s", next_one);
  1664. #endif
  1665.  
  1666.     if(!dfind(&dta_str, next_one, 0))
  1667.     {
  1668.         do
  1669.         {
  1670.             char s[FMSIZE];
  1671.         
  1672.             sprintf(s, "%s%s", folder, dta_str.name);
  1673. #ifdef DEBUG
  1674.             status_line(">Killing %s", s);
  1675. #endif
  1676.             unlink(s);
  1677.             flag++;
  1678.         }
  1679.         while(!dnext(&dta_str));
  1680.     }
  1681.     return flag;
  1682. }
  1683.  
  1684. void kill_bad( void )
  1685. {
  1686.     char *domain = domain_name[0];
  1687.     int k = 0;
  1688.     int counter = 0;
  1689.  
  1690.     status_line(msgtxt[M_KILLING]);
  1691.  
  1692.     /* for each domain */
  1693.  
  1694.     do
  1695.     {
  1696.         /* for each zone */
  1697.  
  1698.         ADDRESS *ad;
  1699.         int count, count1;
  1700.         int ourzone[ALIAS_CNT];    /* record of our own zones */
  1701.         int zonecnt;
  1702.  
  1703.         lock_nodelist(TRUE);        /* keep nodelist file open */
  1704.  
  1705.         /*
  1706.          * do our own zones first
  1707.          */
  1708.         
  1709.         ad = alias;
  1710.         count = num_addrs;
  1711.         zonecnt = 0;
  1712.         while(count--)
  1713.         {
  1714.             if(!domain || (ad->ad.Domain == domain))
  1715.             {
  1716.                 /* check we havnt already done it */
  1717.                     
  1718.                 count1 = zonecnt;
  1719.                 while(count1--)
  1720.                 {
  1721.                     if(ourzone[count1] == ad->ad.Zone)
  1722.                         break;
  1723.                 }
  1724.                 if(count1 < 0)
  1725.                 {
  1726.                     counter += kill_badzone(&ad->ad);
  1727.                     ourzone[zonecnt++] = ad->ad.Zone;
  1728.                 }
  1729.             }
  1730.             ad++;
  1731.         }
  1732.  
  1733.         if(!no_zones)
  1734.         {
  1735.             int zone;
  1736.             
  1737.             do
  1738.             {
  1739.                 ADDR tmp;
  1740.  
  1741.                 tmp.Zone = -1;
  1742.                 tmp.Domain = domain;
  1743.                 tmp.Net = 
  1744.                 tmp.Node = 
  1745.                 tmp.Point = 0;
  1746.             
  1747.                 zone = nodefind(&tmp, 0);
  1748.                 if(zone > 0)
  1749.                 {
  1750.                     /* check we havnt already done it */
  1751.                     
  1752.                     count = zonecnt;
  1753.                     while(count--)
  1754.                     {
  1755.                         if(ourzone[count] == zone)
  1756.                             break;
  1757.                     }
  1758.                     if(count < 0)
  1759.                     {
  1760.                         tmp.Zone = zone;
  1761.                         counter += kill_badzone(&tmp);
  1762.                     }
  1763.                 }
  1764.             } while(zone > 0);
  1765.         }
  1766.  
  1767.         lock_nodelist(FALSE);        /* unlock nodelist */
  1768.  
  1769.         domain = domain_name[++k];
  1770.  
  1771.     } 
  1772.     while (domain != NULL);
  1773.  
  1774. #ifdef DEBUG
  1775.     status_line(">%d $$ files deleted", counter);
  1776. #endif
  1777.  
  1778.     if(counter)
  1779.         set_up_outbound();
  1780. }
  1781.  
  1782. void set_up_outbound( void )
  1783. {
  1784.     MAILP mp;
  1785.  
  1786.     xmit_reset ();
  1787.  
  1788.     /* and remember where we left off */
  1789.     if (hist.next_net != 0)
  1790.     {
  1791.         next_addr.Zone = hist.next_zone;
  1792.         next_addr.Net = hist.next_net;
  1793.         next_addr.Node = hist.next_node;
  1794.         next_addr.Point = hist.next_point;
  1795.         if(hist.next_Domain[0])
  1796.             next_addr.Domain = find_domain(hist.next_Domain);
  1797.         else
  1798.             next_addr.Domain = NULL;
  1799.         mp = find_mail (&next_addr);
  1800.         if ((mp == NULL) || (mp->prev == NULL))
  1801.         {
  1802.             next_mail = NULL;
  1803.             xmit_window (mail_top);
  1804.         }
  1805.         else
  1806.         {
  1807.             next_mail = mp->prev;
  1808.             xmit_window (mail_top);
  1809.         }
  1810.     }
  1811.     else
  1812.     {
  1813.         next_addr.Zone = 
  1814.         next_addr.Net = 
  1815.         next_addr.Node = 
  1816.         next_addr.Point = 0;
  1817.         next_addr.Domain = NULL;
  1818.         xmit_window (mail_top);
  1819.     }
  1820. }
  1821.  
  1822. /*
  1823.  * functions
  1824.  */
  1825.  
  1826. static void minute (void);
  1827. void minute ()
  1828. {
  1829.     if (! (--reinit_ctr))
  1830.     {
  1831.         reinit_ctr = reinit_time;
  1832.         set_prior (4);
  1833.         mdm_init (modem_init);
  1834.         set_prior (2);
  1835.         screen_blank = 1;
  1836.         if (fullscreen)
  1837.             sb_show ();
  1838.     }
  1839.  
  1840.     if (! (--readhold_ctr))
  1841.     {
  1842.         readhold_ctr = readhold_time;
  1843.         set_up_outbound ();
  1844.         more_mail = 1;
  1845.     }
  1846.  
  1847.     put_up_time ();
  1848.     list_next_event ();
  1849. }
  1850.  
  1851. /*
  1852.  * Pick a time between now and x seconds
  1853.  */
  1854.  
  1855. long random_time( int x )
  1856. {
  1857.     int i;
  1858.  
  1859.     if (x == 0)
  1860.     {
  1861.         return (0L);
  1862.     }
  1863.  
  1864.     /* Number of seconds to delay is random based on x +/- 50% */
  1865.     i = (rand () % (x + 1)) + (x / 2);
  1866.  
  1867.     return (timerset ((long)i * 100));
  1868. }
  1869.  
  1870. /*-------------------------------------------------------------------
  1871.  * The main unattended mailer function
  1872.  */
  1873.  
  1874. int unattended( void )
  1875. {
  1876.     MAILP mp;
  1877.     int i, m, j, tmp;
  1878.         long t, t1;                           /* used for the timeouts  */
  1879.     int done = 1;                                 /* if we exit with this, get
  1880.                                                       * out of BT */
  1881.     FILE *tfile;
  1882.     char jbuf[60];
  1883.  
  1884.     un_attended = 1;
  1885.  
  1886. #if 0
  1887.     clear_statusline ();
  1888. #endif
  1889.  
  1890.     comm_bits = BITS_8;
  1891.     parity = NO_PARITY;
  1892.     stop_bits = STOP_1;
  1893.     set_prior(4);                                     /* Always High */
  1894.     MDM_ENABLE (lock_baud && (btypes[baud].rate_value >= lock_baud) ? max_baud.rate_mask : btypes[baud].rate_mask);
  1895.     set_prior(2);                                     /* Regular  */
  1896.  
  1897.     if (fullscreen)
  1898.     {
  1899.         screen_clear ();
  1900.         sb_dirty ();
  1901.     }
  1902.  
  1903.     opening_banner ();
  1904.  
  1905.     if (fullscreen)
  1906.     {
  1907.         mailer_banner ();
  1908.     }
  1909.  
  1910.     if ((tfile = fopen ("BINKLEY.BAN", read_binary)) != NULL)
  1911.     {
  1912.         (void) fread (BBSwelcome, 1, 1000, tfile);
  1913.         (void) fclose (tfile);
  1914.     }
  1915.     else
  1916.     {
  1917.         BBSwelcome[0] = '\0';
  1918.     }
  1919.  
  1920.     /* Initialize the random number generator */
  1921.     i = (int) time (NULL);
  1922.     srand ((unsigned int) i);
  1923.  
  1924. #ifdef ATARIST
  1925.     status_line ("+%s, %s [%s], %s %ld",
  1926.         msgtxt[M_BEGIN], xfer_id, compile_date, msgtxt[M_FREEMEM], Malloc(-1L));
  1927. #else
  1928.     status_line ("+%s, %s", msgtxt[M_BEGIN], xfer_id);
  1929. #endif
  1930.     /*set_xy ("");*/
  1931.     set_prior(4);                                     /* Always High */
  1932.     XON_DISABLE ();
  1933.     set_prior(2);                                     /* Regular  */
  1934.  
  1935.     /* Turn off forced events */
  1936.     if (noforce)
  1937.     {
  1938.         find_event ();
  1939.         noforce = 0;
  1940.     }
  1941.     if (redo_dynam)
  1942.     {
  1943.         for (i = 0; i < num_events; i++)
  1944.         {
  1945.             e_ptrs[i]->behavior &= ~MAT_SKIP;
  1946.         }
  1947.         redo_dynam = 0;
  1948.     }
  1949.  
  1950.     /*
  1951.      * See if we should exit before initializing the modem (and therefore
  1952.      * possibly letting a call sneak through)
  1953.      */
  1954.     find_event ();
  1955.     do_ready (msgtxt[M_READY_INIT]);
  1956.  
  1957.     /* Make sure we have all necessary parameters and that the nodelist
  1958.      * index gets read in. If not, then we must exit right now.
  1959.      */
  1960.  
  1961.     next_addr = alias[0].ad;    /* Does our node exist (or our boss if we're a point */
  1962.     next_addr.Point = 0;
  1963.  
  1964.     if(!net_params || !nodefind(&next_addr, 0))
  1965.         if(alias[0].ad.Net != -1U)
  1966.         {
  1967.             status_line (msgtxt[M_MISCONFIGURED]);
  1968.             errl_exit (254);
  1969.         }
  1970.  
  1971.     /* Set up outbound mail */
  1972.     list_next_event ();
  1973.     set_up_outbound ();
  1974.  
  1975.     if (!CARRIER)
  1976.     {
  1977.         set_prior(4);                                      /* Always High */
  1978.         mdm_init (modem_init);                             /* Reinitialize the modem  */
  1979.         set_prior(2);                                      /* Regular  */
  1980.     }
  1981.  
  1982.     t1 = timerset ((long)next_minute ());                             /* Set a 1 minute timer  */
  1983.  
  1984.  
  1985. top_of_mail:
  1986.     un_attended = 1;
  1987.     i = 0;
  1988.     m = 1;
  1989.  
  1990.     /* As long as we don't press a key */
  1991. bad_char:
  1992.     more_mail = 1;
  1993.     while (!(KEYPRESS () || ctrlc_ctr))
  1994.     {
  1995.         find_event ();
  1996.  
  1997.         /* Show that we are ready */
  1998.         if (m)
  1999.         {
  2000.             if (fullscreen)
  2001.             {
  2002.                 do_ready (msgtxt[M_READY_WAITING]);
  2003.                 list_next_event ();
  2004.             }
  2005.             else
  2006.             {
  2007.                 status_line (msgtxt[M_EVENT_WAITING], cur_event + 1);
  2008.             }
  2009.             t1 = timerset ((long)next_minute ());                          /* Set a 1 minute timer */
  2010.         }
  2011.  
  2012.         if (timeup (t1))
  2013.         {
  2014.             minute ();
  2015.             t1 = timerset ((long)next_minute ());                               /* Set a 1 minute timer */
  2016.         }
  2017.  
  2018.         m = 0;
  2019.  
  2020.         if (cur_event >= 0)
  2021.         {
  2022.             i = (e_ptrs[cur_event]->behavior & MAT_OUTONLY);
  2023.             t = random_time (e_ptrs[cur_event]->wait_time);
  2024.         }
  2025.         else
  2026.         {
  2027.             i = 1;
  2028.             t = random_time (5);
  2029.         }
  2030.  
  2031.      /*  variable 'i' will be TRUE if we are either manually dialing out
  2032.       *  or if we are in an event where we do not want incoming stuff.
  2033.       */
  2034.  
  2035.         while ((!timeup (t)) && (!KEYPRESS ()) && (m == 0) && !ctrlc_ctr)
  2036.         {
  2037.  
  2038.             find_event ();
  2039.  
  2040.             time_release ();
  2041.  
  2042.             if (timeup (t1))
  2043.             {
  2044.                 minute ();
  2045.                 t1 = timerset ((long)next_minute ());                             /* Set a 1 minute timer */
  2046.             }
  2047.  
  2048.             /* If we want inbound, see if there is any. If we send
  2049.                         anything, clean up afterwards ...       */
  2050.  
  2051.             if (!i)
  2052.             {
  2053.                 m = handle_inbound_mail ();
  2054.                 if (m)
  2055.                     set_up_outbound ();
  2056.             }
  2057.         }
  2058.  
  2059.         if ((m) && (fullscreen))
  2060.         {
  2061.             do_ready (msgtxt[M_READY_WAITING]);
  2062.             list_next_event ();
  2063.         }
  2064.  
  2065. immed_call:
  2066.  
  2067.         find_event ();
  2068.  
  2069.         /* If we are not in an event, loop again */
  2070.         if (cur_event < 0)
  2071.         {
  2072.             time_release ();
  2073.             continue;
  2074.         }
  2075.  
  2076.         /* If we have pressed a key, get out */
  2077.         if (KEYPRESS () || ctrlc_ctr)
  2078.             break;
  2079.  
  2080.         /* See if we are supposed to do any mail */
  2081.         if (cur_event >= 0)
  2082.             if (e_ptrs[cur_event]->behavior & MAT_NOOUT)
  2083.             {
  2084.                 continue;
  2085.             }
  2086.  
  2087.         if (more_mail)
  2088.         {
  2089.             more_mail = xmit_next (&next_addr);
  2090.             if (more_mail)
  2091.             {
  2092.                 /* save the next call in the list in case we exit */
  2093.  
  2094.                 if ((next_mail == NULL) || (next_mail->next == NULL))
  2095.                     mp = mail_top;
  2096.                 else
  2097.                     mp = next_mail->next;
  2098.  
  2099.                 hist.next_zone = mp->mail_addr.Zone;
  2100.                 hist.next_net = mp->mail_addr.Net;
  2101.                 hist.next_node = mp->mail_addr.Node;
  2102.                 hist.next_point = mp->mail_addr.Point;
  2103.                 memset(hist.next_Domain, 0, sizeof(hist.next_Domain));
  2104.                 if(mp->mail_addr.Domain)
  2105.                     strcpy(hist.next_Domain, mp->mail_addr.Domain);
  2106.  
  2107.                 set_prior(4);                                        /* Always High */
  2108.                 m = do_mail (&next_addr, 0);
  2109.                 set_prior(2);                                        /* Regular */
  2110.  
  2111.                 if(m == 1)        /* Connected with carrier */
  2112.                 {
  2113.                     if (!sent_mail)
  2114.                     {
  2115.                         /* We connected but the transfer didn't work */
  2116.                         bad_call (&next_addr, BAD_CARRIER);
  2117.                         xmit_window (next_mail);
  2118.                     }
  2119.                     else
  2120.                     {
  2121.                         set_up_outbound();
  2122.                     }
  2123.                 }
  2124.  
  2125.                 else if (m == 2)                                         /* Nothing happened */
  2126.                 {
  2127.                     bad_call (&next_addr, BAD_NOCARRIER);
  2128.                 }
  2129.  
  2130.                 else if (m == -1)
  2131.                 {
  2132.                     status_line (msgtxt[M_INCOMING_CALL]);
  2133.                 }
  2134.             }
  2135.         }
  2136.  
  2137.         if (!more_mail)
  2138.         {
  2139.             /* No more mail to do, was it dynamic? */
  2140.             if (cur_event >= 0)
  2141.                 if (e_ptrs[cur_event]->behavior & MAT_DYNAM)
  2142.                 {
  2143.                     if (!blank_on_key)
  2144.                         screen_blank = 0;
  2145.                     e_ptrs[cur_event]->behavior |= MAT_SKIP;
  2146.                     status_line (":%s %s %d", msgtxt[M_END_OF], msgtxt[M_DYNAMIC_EVENT], cur_event + 1);
  2147.                     goto top_of_mail;
  2148.                 }
  2149.         }
  2150.     }
  2151.  
  2152.     /*-----------------------------------------------------------------
  2153.      * We get to here if a key is pressed
  2154.      *
  2155.      * If the code was laid out better and the labels and goto's were
  2156.      * converted into looping constructs this would be much easier to read.
  2157.      */
  2158.  
  2159.  
  2160.     /* any key to unblank, SWG 24th June 1991 */
  2161.     if(screen_blank && do_screen_blank)
  2162.     {
  2163.         if(KEYPRESS())                        /* Clear the key */
  2164.             FOSSIL_CHAR();
  2165.         screen_blank = 0;                /* Unblank the screen */
  2166.         if(fullscreen)                        /* Redisplay the screen */
  2167.             sb_show();
  2168.         goto bad_char;
  2169.     }
  2170.  
  2171.     /* No key press should not exit! SWG 24th June 1991 */
  2172.     if(ctrlc_ctr)
  2173.     {
  2174.  
  2175.            /*
  2176.          * Be serious, there had to be a key pressed or we wouldn't be here I
  2177.          * know it sounds silly, but ^C will sometimes do crap like this
  2178.          */
  2179.         status_line (msgtxt[M_EXIT_REQUEST]);
  2180.     }
  2181.     else
  2182.     {
  2183.             /* No keypress available then continue, SWG 24th June 1991 */
  2184.             if(!KEYPRESS())
  2185.                 goto bad_char;                /* May as well be using Basic with all these goto's!!! */
  2186.             i = (int) FOSSIL_CHAR ();
  2187. #ifndef ATARIST
  2188.             if ((i & 0xff) == 0)
  2189.             {
  2190. #endif
  2191.                 switch (i)
  2192.                 {
  2193.                 case PF1:
  2194.                 case PF2:
  2195.                 case PF3:
  2196.                 case PF4:
  2197.                 case PF5:
  2198.                 case PF6:
  2199.                 case PF7:
  2200.                 case PF8:
  2201.                 case PF9:
  2202.                 case PF10:
  2203.                 
  2204.                     j = (int) (((unsigned) i) >> 8);
  2205.                     status_line (msgtxt[M_FUNCTION_KEY], (j - 0x3a) * 10);
  2206.                     errl_exit ((j - 0x3a) * 10);
  2207.                     break;
  2208.  
  2209.                 /* ANSWER  24.05.1990 */
  2210.                 case ALTA:
  2211.                     CLEAR_INBOUND ();
  2212.                     mdm_cmd_string (ans_str, 0);                      /* transmit the answer */
  2213.                     m = handle_inbound_mail ();
  2214.                     if (m)
  2215.                     {
  2216.                         /* If we sent out anything, make sure we reset stuff */
  2217.                         set_up_outbound ();
  2218.                     }
  2219.                     goto bad_char;
  2220.  
  2221.                 case ALTB:
  2222.                     screen_blank = 1;
  2223.                     if (fullscreen)
  2224.                         sb_show ();
  2225.                     goto bad_char;
  2226.  
  2227.                 case ALTC:
  2228.                     tmp = hist.which_day;
  2229.                     (void) memset (&hist, 0, sizeof (HISTORY));
  2230.                     hist.which_day = tmp;
  2231.                     if (fullscreen)
  2232.                     {
  2233.                         do_today ();
  2234.                         sb_show ();
  2235.                     }
  2236.                     goto bad_char;
  2237.  
  2238.                 case ALTE:
  2239.                 case CTRLM:        /* Control M for ACS compatibility */
  2240.                     if (BBSreader != NULL)
  2241.                     {
  2242.                         vfossil_cursor (1);
  2243.                         status_line (msgtxt[M_DISABLE_MODEM]);
  2244.                         set_prior(4);                                          /* Always High */
  2245.                         mdm_init (modem_busy);
  2246.                         exit_DTR ();
  2247.                         set_prior(2);                                          /* Regular */
  2248.                         status_line (msgtxt[M_BEGIN_MESSAGE_READER]);
  2249.                         vfossil_close ();
  2250.                         b_spawn (BBSreader);
  2251.                         vfossil_init ();
  2252.                         if (fullscreen)
  2253.                         {
  2254.                             screen_clear ();
  2255.                             sb_dirty ();
  2256.                             opening_banner ();
  2257.                             mailer_banner ();
  2258.                         }
  2259.                         status_line (msgtxt[M_END_MESSAGE_READER]);
  2260.                         set_up_outbound ();
  2261.                         m = 1;
  2262.                         more_mail = 1;
  2263.                         status_line (msgtxt[M_ENABLE_MODEM]);
  2264.                         set_prior(4);                                          /* Always High */
  2265.                         DTR_ON ();
  2266.                         mdm_init (modem_init);
  2267.                         set_prior(2);                                          /* Regular */
  2268.                         goto top_of_mail;
  2269.                     }
  2270.                     else
  2271.                     {
  2272.                         set_xy (NULL);
  2273.                         status_line (msgtxt[M_NO_MESSAGE_READER]);
  2274.                         set_xy (NULL);
  2275.                         m = 1;
  2276.                         goto bad_char;
  2277.                     }
  2278.  
  2279.                 /* NICEOUTBOUND  09.09.1990 */
  2280.                 case ALTF:
  2281.                     niceoutbound = 1-niceoutbound;
  2282.                     if (niceoutbound)
  2283.                     {
  2284.                         xmit_reset ();
  2285.                     }
  2286.                     else
  2287.                     {
  2288. #if 0
  2289.                         next_mail = mail_top;
  2290. #endif
  2291.                         xmit_window (next_mail);
  2292.                     }
  2293.                     goto bad_char;
  2294.  
  2295.                 /* Roland's flavour changer */
  2296.  
  2297.                 case CTRLC:
  2298.                 case CTRLF:
  2299.                     if (sb_popup (10, 10, 6, 60, Do_Change, 0))
  2300.                         status_line (msgtxt[M_NO_CHANGE]);
  2301.                     else
  2302.                     {
  2303.                         set_up_outbound ();
  2304.                         m = 1;
  2305.                         more_mail = 1;
  2306.                     }
  2307.                     goto bad_char;
  2308.  
  2309.                 case ALTG:
  2310.                     /* ONEMORE  01.09.1990 */
  2311.                     if (sb_popup (10, 10, 6, 60, Do_Get, 0))
  2312.                     {
  2313.                         status_line (msgtxt[M_NO_GET]);
  2314.                     }
  2315.                     else
  2316.                     {
  2317.                         set_up_outbound ();
  2318.                         m = 1;
  2319.                         more_mail = 1;
  2320.                     }
  2321.                     goto bad_char;
  2322.  
  2323.                 case ALTI:
  2324.                     /* FASTMODEM, REINIT  18.07.1990 */
  2325.                     mdm_hangup ();
  2326.                     reinit_ctr = reinit_time;
  2327.                     m = 1;
  2328.                     goto bad_char;
  2329.                 case ALTJ:
  2330.                     status_line (msgtxt[M_SHELLING]);
  2331.                     /* EXEC  18.07.1990 */
  2332.                     set_prior(4);
  2333.                     mdm_init (modem_busy);
  2334.                     exit_DTR ();
  2335.                     set_prior(2);
  2336.                     if (fullscreen) screen_clear ();
  2337.                     vfossil_cursor (1);
  2338.                     (void) cputs (msgtxt[M_TYPE_EXIT]);
  2339.                     close_up ();
  2340.                     change_prompt ();
  2341.                     b_spawn (NULL);
  2342.                     come_back ();
  2343.                     m = 1;
  2344.                     set_up_outbound ();
  2345.                     set_prior(4);                                         /* Always High */
  2346.                     DTR_ON ();
  2347.                     mdm_init (modem_init);
  2348.                     reinit_ctr = reinit_time;
  2349.                     status_line (msgtxt[M_BINKLEY_BACK]);
  2350.                     set_prior(2);                                         /* Regular */
  2351.                     goto bad_char;
  2352.  
  2353.                 case ALTK:
  2354.                     if (sb_popup (10, 5, 4, 70, Do_Kill, 0))
  2355.                     {
  2356.                         status_line (msgtxt[M_NO_KILL]);
  2357.                     }
  2358.                     else
  2359.                     {
  2360.                         set_up_outbound ();
  2361.                         m = 1;
  2362.                         more_mail = 1;
  2363.                     }
  2364.                     goto bad_char;
  2365.  
  2366.                 case ALTY:
  2367.                     next_addr = alias[0].ad;    /* Poll ourself */
  2368.                     next_addr.Point = 0;        /* Remove the point to get boss */
  2369.                     goto polling;
  2370.  
  2371.                 /* ZOOM  27.08.1990 */
  2372.                 case ALTZ:
  2373.                     if (sb_popup (1, 1, SB_ROWS-2, 78, Overlay_Do_Zoom, 0))
  2374.                     {
  2375.                     }
  2376.                     goto bad_char;
  2377.  
  2378.                 case ALTM:
  2379.                     status_line (msgtxt[M_POLL_MODE]);
  2380.                     if (fullscreen)
  2381.                         gotoxy (0, SB_ROWS - 2);
  2382.                     vfossil_cursor (1);
  2383.                     scr_printf ("\r\n");
  2384.                     clear_eol ();
  2385.                     scr_printf (msgtxt[M_ENTER_NET_NODE]);
  2386.                     m = get_number (jbuf);
  2387.                     if (m)
  2388.                     {
  2389.                         m = find_address (jbuf, &next_addr);
  2390.                     }
  2391.                     if (fullscreen)
  2392.                     {
  2393.                         gotoxy (0, SB_ROWS - 1);
  2394.                         clear_eol ();
  2395.                         bottom_line ();
  2396.                         vfossil_cursor (0);
  2397.                         sb_show ();
  2398.                     }
  2399.                     if (m >= 1 && nodefind (&next_addr, 1))
  2400.                     {
  2401.                         if (!next_addr.Zone)
  2402.                             next_addr.Zone = found_zone;
  2403.  
  2404.                         /* Warn user that it is not CM */
  2405.  
  2406.                         if ( (cur_event < 0 || (e_ptrs[cur_event]->behavior & MAT_NOCM))
  2407.                             && (!(newnodedes.NodeFlags & B_CM)))
  2408.                         {
  2409.                             int c;
  2410.  
  2411.                             if (fullscreen)
  2412.                                 gotoxy (0, SB_ROWS - 2);
  2413.                             vfossil_cursor (1);
  2414.                             scr_printf ("\r\n");
  2415.                             clear_eol ();
  2416.                             scr_printf ("WARNING: ");
  2417.                             scr_printf(Pretty_Addr_Str(&next_addr));
  2418.                             scr_printf(" is not 24 Hours... poll anyway(Y/N)?");
  2419.                             while (!KEYPRESS ())
  2420.                                 time_release ();
  2421.                             c = FOSSIL_CHAR ();
  2422.                             if (fullscreen)
  2423.                             {
  2424.                                 gotoxy (0, SB_ROWS - 1);
  2425.                                 clear_eol ();
  2426.                                 bottom_line ();
  2427.                                 vfossil_cursor (0);
  2428.                                 sb_show ();
  2429.                             }
  2430.                             if(toupper(c) != 'Y')
  2431.                             {
  2432.                                 status_line("#Poll aborted");
  2433.                                 goto bad_char;
  2434.                             }
  2435.                         }
  2436. polling:
  2437.                         doing_poll = 1;
  2438.                         if (fullscreen)
  2439.                         {
  2440.                             sb_move (filewin, 1, 2);
  2441.                             sb_puts (filewin, (unsigned char *) msgtxt[M_CURRENTLY_POLLING]);
  2442.                             sb_puts (filewin, (unsigned char *) Pretty_Addr_Str (&next_addr));
  2443.                         }
  2444.                         set_prior(4);                        /* Always High */
  2445.                         if (do_mail (&next_addr, 1) == 1)
  2446.                         {
  2447.                             if(sent_mail)
  2448.                                 set_up_outbound();
  2449.                             else
  2450.                                 xmit_window (next_mail);
  2451.                         }
  2452.                             
  2453.                         set_prior(2);                        /* Regular */
  2454.                         doing_poll = 0;
  2455.                     }
  2456.                     status_line (msgtxt[M_POLL_COMPLETED]);
  2457.                     if (fullscreen)
  2458.                     {
  2459.                         clear_filetransfer ();
  2460.                     }
  2461.                     set_prior(4);                            /* Always High */
  2462.                     DTR_ON ();
  2463.                     mdm_init (modem_init);
  2464.                     set_prior(2);                            /* Regular */
  2465.                     m = 1;
  2466.                     goto bad_char;
  2467.  
  2468.                 /* OUTBOUND  23.10.1989 */
  2469.                 case ALTO:
  2470.                     set_up_outbound ();
  2471.                     m = 1;
  2472.                     more_mail = 1;
  2473.                     goto bad_char;
  2474.  
  2475.                 case ALTQ:
  2476.                     if (cur_event >= 0)
  2477.                         e_ptrs[cur_event]->behavior |= MAT_SKIP;
  2478.                     goto top_of_mail;
  2479.  
  2480.                 case ALTR:
  2481.                     for (j = 0; j < num_events; j++)
  2482.                     {
  2483.                         /* Don't redo forced events */
  2484.                         if (!(e_ptrs[j]->behavior & MAT_FORCED))
  2485.                         {
  2486.                             e_ptrs[j]->last_ran = -1;
  2487.                             e_ptrs[j]->behavior &= ~MAT_SKIP;
  2488.                         }
  2489.                     }
  2490.                     goto top_of_mail;
  2491.  
  2492.                 case ALTS:
  2493.                     if (sb_popup (10, 5, 6, 70, Do_Send, 0))
  2494.                     {
  2495.                         status_line (msgtxt[M_NO_SEND]);
  2496.                     }
  2497.                     else
  2498.                     {
  2499.                         set_up_outbound ();
  2500.                         m = 1;
  2501.                         more_mail = 1;
  2502.                     }
  2503.                     goto bad_char;
  2504.  
  2505.                 case ALTT:
  2506. #ifdef ATARIST
  2507.                 case UNDO:
  2508. #endif            
  2509.                     status_line (msgtxt[M_ENTER_TERMINAL_MODE]);
  2510.                     b_init ();
  2511.                     done = 0;                                             /* We won't exit now */
  2512.                     goto mail_done;
  2513.  
  2514.                 case ALTW:
  2515.                     if (fullscreen)
  2516.                     {
  2517.                         screen_clear ();
  2518.                         sb_dirty ();
  2519.                         sb_show ();
  2520.                     }
  2521.                     goto bad_char;
  2522.                     
  2523. #if N_SHELLS < 10
  2524.                 case ALTF10:
  2525. #endif            
  2526. #ifdef ATARIST
  2527.                 case HELP:
  2528. #endif                        
  2529.                     mailer_help ();
  2530.                     if (fullscreen)
  2531.                     {
  2532.                         screen_clear ();
  2533.                         sb_dirty ();
  2534.                         opening_banner ();
  2535.                         mailer_banner ();
  2536.                     }
  2537.                     m = 1;
  2538.                     goto bad_char;
  2539.  
  2540.                 case ALTX:
  2541.                 case CTRLQ:        /* ^Q for ACS compatibility */
  2542.                     status_line (msgtxt[M_EXIT_REQUEST]);
  2543.                     goto mail_done;
  2544.  
  2545.                 case ALTF1:
  2546.                 case ALTF2:
  2547.                 case ALTF3:
  2548.                 case ALTF4:
  2549.                 case ALTF5:
  2550.                 case ALTF6:
  2551.                 case ALTF7:
  2552.                 case ALTF8:
  2553.                 case ALTF9:
  2554. #if N_SHELLS >= 10
  2555.                 case ALTF10:
  2556. #endif
  2557.                     j = (int) (((unsigned) i) >> 8) - ((unsigned)ALTF1>>8);
  2558.                     if (shells[j] != NULL)
  2559.                     {
  2560.                         /* GENERALEXEC  24.09.1989 */
  2561.                         exec_shell (++j);
  2562.                         m = 1;
  2563.                         goto top_of_mail;
  2564.                     }
  2565.  
  2566.                     status_line (msgtxt[M_NO_KEYBOARD_SHELL], j + 1);
  2567.                     goto bad_char;
  2568.  
  2569.                 case PGUP:
  2570.                     if (next_mail == NULL)
  2571.                         next_mail = mail_top;
  2572.  
  2573.                     if (next_mail != NULL)
  2574.                     {
  2575.                         for (j = 0; j < 4; j++)
  2576.                         {
  2577.                             if (next_mail->prev != NULL)
  2578.                                 next_mail = next_mail->prev;
  2579.                         }
  2580.                         xmit_window (next_mail);
  2581.                     }
  2582.                     goto bad_char;
  2583.  
  2584.                 case PGDN:
  2585.                     if (next_mail == NULL)
  2586.                     {
  2587.                         next_mail = mail_top;
  2588.                     }
  2589.  
  2590.                     if (next_mail != NULL)
  2591.                     {
  2592.                         for (j = 0; j < 4; j++)
  2593.                         {
  2594.                             if (next_mail->next != NULL)
  2595.                                 next_mail = next_mail->next;
  2596.                         }
  2597.                         xmit_window (next_mail);
  2598.                     }
  2599.                     goto bad_char;
  2600.  
  2601.                 case UPAR:
  2602.                     if (next_mail == NULL)
  2603.                     {
  2604.                         next_mail = mail_top;
  2605.                     }
  2606.  
  2607.                     if (next_mail != NULL)
  2608.                     {
  2609.                         if (next_mail->prev != NULL)
  2610.                             next_mail = next_mail->prev;
  2611.                         xmit_window (next_mail);
  2612.                     }
  2613.                     goto bad_char;
  2614.  
  2615.                 case DNAR:
  2616.                     if (next_mail == NULL)
  2617.                     {
  2618.                         next_mail = mail_top;
  2619.                     }
  2620.  
  2621.                     if (next_mail != NULL)
  2622.                     {
  2623.                         if (next_mail->next != NULL)
  2624.                             next_mail = next_mail->next;
  2625.                         xmit_window (next_mail);
  2626.                     }
  2627.                     goto bad_char;
  2628.  
  2629.                 case HOME:
  2630.                     next_mail = mail_top;
  2631.                     xmit_window (next_mail);
  2632.                     goto bad_char;
  2633.  
  2634.                 case END:
  2635.                     if (next_mail == NULL)
  2636.                     {
  2637.                         next_mail = mail_top;
  2638.                     }
  2639.  
  2640.                     if (next_mail != NULL)
  2641.                     {
  2642.                         while (next_mail->next != NULL)
  2643.                         {
  2644.                             next_mail = next_mail->next;
  2645.                         }
  2646.                     }
  2647.  
  2648.                     for (j = 0; j < 3; j++)
  2649.                     {
  2650.                         if (next_mail->prev != NULL)
  2651.                             next_mail = next_mail->prev;
  2652.                     }
  2653.                     xmit_window (next_mail);
  2654.                     goto bad_char;
  2655.  
  2656. #ifndef ATARIST
  2657.                 default:
  2658.                     status_line (msgtxt[M_JUNK_CHARACTER]);
  2659.                     m = 1;
  2660.                     goto bad_char;
  2661.                 }
  2662.             }
  2663.             else
  2664.             {
  2665.                 switch (i & 0xff)
  2666.                 {
  2667. #endif
  2668.                 case ESC:
  2669.                     m = sb_popup(10,2, 3,74, do_shell, 0);
  2670.                     goto bad_char;
  2671.  
  2672.                 case 'C':
  2673.                 case 'c':
  2674.                     if (cur_event >= 0)
  2675.                         if (e_ptrs[cur_event]->behavior & MAT_NOOUT)
  2676.                         {
  2677.                             status_line (msgtxt[M_NO_CALLS_NOW]);
  2678.                             goto immed_call;
  2679.                         }
  2680.  
  2681.                     status_line (msgtxt[M_IMMEDIATE_CALL]);
  2682.                     m = 0;
  2683.                     more_mail = 1;
  2684.                     goto immed_call;
  2685.  
  2686.                 case '$':
  2687.                     kill_bad();
  2688.                     goto bad_char;
  2689.  
  2690. #ifndef ATARIST        /* Put in same place as Alt-X */
  2691.                 case 3:
  2692.                     status_line (msgtxt[M_EXIT_REQUEST]);
  2693.                     goto mail_done;
  2694. #endif
  2695.  
  2696.                 case 0x20:
  2697.                     m = 1;
  2698.                     goto bad_char;
  2699.  
  2700.                 default:
  2701.                     status_line (msgtxt[M_JUNK_CHARACTER]);
  2702.                     m = 1;
  2703.                     goto bad_char;
  2704.                 }
  2705. #ifndef ATARIST
  2706.             }
  2707. #endif
  2708.         }
  2709.  
  2710. mail_done:
  2711.     write_sched ();
  2712.     status_line ("+%s, %s", msgtxt[M_END], xfer_id);
  2713.     un_attended = 0;
  2714.     if (fullscreen)
  2715.     {
  2716.         gotoxy (0, SB_ROWS);
  2717.     }
  2718.     set_prior(4);                                     /* Always High */
  2719.     XON_ENABLE ();
  2720.     set_prior(2);                                     /* Regular */
  2721.     return (done);
  2722. }
  2723.