home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / VP2_409E.SZH / SCAN.C < prev    next >
Text File  |  1991-06-27  |  41KB  |  1,206 lines

  1. /*
  2.   $Header: scan.c 3.31 87/12/31 14:53:56 Bob Exp $
  3.  
  4.                           The Conference Mail System
  5.  
  6.               This module was originally written by Bob Hartman
  7.                        Sysop of FidoNet node 1:132/101
  8.  
  9.    Spark Software, 427-3 Amherst St, CS 2032, Suite 232, Nashua, NH 03061
  10.  
  11.  The Conference Mail System  is a  complete Echomail processing package.  It
  12.  is a superset of the original  Echomail utilities created by Jeff Rush, and
  13.  also contains ideas gleaned from the  ARCmail,  Renum,  oMMM, MGM, and Opus
  14.  programs that were created by various software authors.
  15.  
  16.  This program source code is being released with the following provisions:
  17.  
  18.  1.  You are  free to make  changes to this source  code for use on your own
  19.  machine,  however,  altered source files may not be distributed without the
  20.  consent of Spark Software.
  21.  
  22.  2.  You may distribute "patches"  or  "diff" files for any changes that you
  23.  have made, provided that the "patch" or "diff" files are also sent to Spark
  24.  Software for inclusion in future releases of the entire package.   A "diff"
  25.  file for the source archives may also contain a compiled version,  provided
  26.  it is  clearly marked as not  being created  from the original source code.
  27.  No other  executable  versions may be  distributed without  the  consent of
  28.  Spark Software.
  29.  
  30.  3.  You are free to include portions of this source code in any program you
  31.  develop, providing:  a) Credit is given to Spark Software for any code that
  32.  may is used, and  b) The resulting program is free to anyone wanting to use
  33.  it, including commercial and government users.
  34.  
  35.  4.  There is  NO  technical support  available for dealing with this source
  36.  code, or the accompanying executable files.  This source  code  is provided
  37.  as is, with no warranty expressed or implied (I hate legalease).   In other
  38.  words, if you don't know what to do with it,  don't use it,  and if you are
  39.  brave enough to use it, you're on your own.
  40.  
  41.  Spark Software may be contacted by modem at (603) 888-8179 (node 1:132/101)
  42.  on the public FidoNet network, or at the address given above.
  43.  
  44.  To use this code you will need Microsoft C version 4.0, and also Microsoft
  45.  Macro Assembler version 4.0.
  46.  
  47. */
  48.  
  49. /*
  50.    $Log:    scan.c $
  51.  * Revision 4.09d 91/06/11            GJS
  52.  * Update for to include statistics and logging
  53.  *
  54.  * Revision 3.31  87/12/31  14:53:56  Bob
  55.  * Fixed bug dealing with nulls embedded in messages
  56.  *
  57.  * Revision 3.3  87/12/12  00:44:48  Bob
  58.  * Source code release
  59.  *
  60. */
  61.  
  62. #include <stdio.h>
  63. #include <ctype.h>
  64. #include <fcntl.h>
  65. #include <io.h>
  66. #include <time.h>
  67. #include <string.h>
  68. #include <sys\types.h>
  69. #include <sys\stat.h>
  70. #include "fastecho.h"
  71.  
  72. #if STATS
  73.    #include "stats.h"
  74. #endif
  75.  
  76. #define DEBUG 0
  77.  
  78. extern char *no_msgs;
  79. extern SEACONFIG config;
  80. extern AREAS_PTR areas[];
  81. extern char board_name[], sysop_name[];
  82. extern int tot_areas;
  83. extern char bbsfile[];
  84. extern char *arc_cmd[];
  85. extern int nread;
  86. extern int arc_args;
  87. extern int last_msg;
  88. extern int high_one;
  89. extern int convert;
  90. extern int notquiet;
  91. extern char seen_byline[];
  92. extern char originline[];
  93. extern char tearline[];
  94. extern int max_msgs;
  95. extern int ctrla;
  96. extern unsigned int def_attr;
  97. extern int boss_net, boss_node;
  98. extern int noforward;
  99. extern int noprivate;
  100. extern int tiny_seen;
  101. extern int priv_net;
  102. extern int zone_net[];
  103. extern int zone_node[];
  104. extern int num_zone;
  105. extern int send_pvt;
  106. extern char tmpjunk[];
  107. extern int *msg_nums;
  108. extern int do_path;
  109. extern int last_opened;
  110. extern struct _stamp zero_stamp;
  111. char *holder1;
  112. int mail_low;
  113. extern int mail_high;
  114. char *seen_by;
  115. char *origin;
  116. char *tear;
  117. char *holder;
  118. int originl;
  119. int seen_byl;
  120. int msgl;
  121. int seen_zones[MAXSEEN];
  122. int seen_nets[MAXSEEN];
  123. int seen_nodes[MAXSEEN];
  124. int path_nets[MAXPATH];
  125. int path_nodes[MAXPATH];
  126. int tot_path;
  127. int not_seen[MAXNODES];
  128. int tot_seen;
  129. int tot_scanned;
  130. char arealine[80];
  131. int areal;
  132. MSG_PTR h;
  133. extern int msgs_done;
  134. extern char *SEENBYSTR;
  135. extern char *PATHSTR;
  136.  
  137. int scan (AREAS_PTR which)
  138. {
  139.     int i, j, k, l, foo, foo1, foo3;
  140.     char *t1, *q1, *s1;
  141.     char *ptr;
  142.     int f;
  143.     int totread;
  144.    int done;
  145.    int new_net, new_node, new_zone, new_point;
  146.    int sbl, ctla;
  147.    char *last_name;
  148.     char fname[80], fname1[80];
  149.  
  150.     f = 0;
  151.    last_name = which->area_name;
  152.    last_opened = -1;
  153. #if DEBUG
  154. printf ("Going to do area name '%s'\n", which->area_name);
  155. #endif
  156.     /* Get the high water mark */
  157.     get_hw (which);
  158.  
  159.     /* Get the list of messages in this area */
  160.     get_msg_lst (msg_nums, &last_msg, which->msg_path, 0);
  161.  
  162.     /* Special case when we have no messages */
  163.     if (last_msg == 0)
  164.         {
  165. #if DEBUG
  166. printf ("really no messages\n");
  167. #endif
  168.         printf (no_msgs, which->area_name);
  169.     set_hw (1, which);
  170.         return (0);
  171.         }
  172.  
  173.     if (high_one >= msg_nums[last_msg-1])
  174.         {
  175. #if DEBUG
  176. printf ("high_one = %d, last = %d\n", high_one, msg_nums[last_msg - 1]);
  177. #endif
  178.         printf (no_msgs, which->area_name);
  179.  
  180.         /* Set the high water mark properly for next time (if necessary) */
  181.         if (high_one != msg_nums[last_msg-1])
  182.             set_hw (msg_nums[last_msg-1], which);
  183.  
  184.         return (0);
  185.         }
  186.     else
  187.         high_one = find_msg (high_one, last_msg, 0);
  188.  
  189.     /* Save how many we started with */
  190.     foo3 = msgs_done;
  191.  
  192.     printf ("Processing messages numbered %d-%d in message area '%s'\n",
  193.         msg_nums[high_one], msg_nums[last_msg-1], which->area_name);
  194.  
  195.  
  196.     #if STATS
  197.         LogScanArea(which->area_name, msg_nums[high_one], msg_nums[last_msg-1]);
  198.     #endif
  199.  
  200. #if DEBUG
  201.     printf ("V_Purge is '%s'\n", (which->flags & V_PURGE)?("ON"):("OFF"));
  202. #endif
  203.  
  204.     /* Save the directory name we are working in */
  205.     strcpy (fname, which->msg_path);
  206.  
  207.     /* Point to where we will be sticking in the file name */
  208.     t1 = fname + strlen (fname);
  209.  
  210.     /* Point to the start of message text */
  211.     holder = holder1+sizeof(MSG);
  212.  
  213.     /* Point to the message header */
  214.     h = (MSG_PTR) holder1;
  215.  
  216.     /* Set up the area name */
  217.     if (ctrla)
  218.         {
  219.         sprintf (arealine, "\001AREA: %s\r", which->area_name);
  220.         }
  221.     else
  222.         {
  223.         sprintf (arealine, "AREA:%s\r", which->area_name);
  224.         }
  225.     areal = strlen (arealine);
  226.  
  227.     /* Process the messages from here to the end */
  228.     for (i = high_one; i < last_msg; i++)
  229.         {
  230.         /* If we have done too many messages, quit */
  231.         if (msgs_done >= max_msgs)
  232.             {
  233.             break;
  234.             }
  235.  
  236.         /* Close the files that might be open */
  237.         if (f>0)
  238.             {
  239.             (void) fast_close (f);
  240.             f = 0;
  241.             }
  242.  
  243.         /* set up message name */
  244.         sprintf (t1, "\\%d.MSG", msg_nums[i]);
  245. #if DEBUG
  246. printf ("Doing file %s\n", fname);
  247. #endif
  248.  
  249.         /* Open the message file */
  250.         if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  251.             {
  252.             printf ("\r%s could not open - continuing\n", fname);
  253.             continue;
  254.             }
  255.  
  256.         /* Read the whole thing in */
  257.         if ((totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG))) <= (sizeof (MSG)))
  258.             {
  259.             printf ("\r%s is a null message - continuing\n", fname);
  260.             continue;
  261.             }
  262.  
  263.       if (totread >= NUMBLOCKS*1024+sizeof(MSG)-10)
  264.          {
  265.          printf ("\r%s is too big a message - continuing\n", fname);
  266.          continue;
  267.          }
  268.  
  269. #if DEBUG
  270. printf ("Read %d chars in message\n", totread-sizeof(MSG));
  271. #endif
  272.  
  273.         /* Now process the header to see if we should scan it at all */
  274.         if ((h->attr & MSGSENT) || (h->orig_net <= -1) || (h->orig < -1))
  275.             {
  276. #if DEBUG
  277. printf ("Did not send because header did not pass\n");
  278. #endif
  279.             continue;
  280.             }
  281.  
  282.       h->date[19] = 0;
  283.       h->_date_written = h->_date_arrived = zero_stamp;
  284.  
  285.       ++tot_scanned;
  286.         if (h->attr & MSGPRIVATE)
  287.          {
  288. #ifndef VPURGE
  289.          if ((which->flags & PASS_THRU) || (which->flags & ROUTETHRU))
  290. #else  /* VPURGE */
  291.          if ((which->flags & PASS_THRU) || (which->flags & ROUTETHRU)
  292.             || (which->flags & V_PURGE))
  293. #endif /* VPURGE */
  294.             {
  295.             goto reg_echo;
  296.             }
  297.          if (send_pvt && h->reply && (h->attr & MSGLOCAL))
  298.             {
  299.             for (j = 1; j <= config.num_addrs; j++)
  300.                {
  301.                if ((h->orig == config.node[j]) && (h->orig_net == config.net[j]))
  302.                   break;
  303.                }
  304.             if (j <= config.num_addrs)
  305.                {
  306.                /* We have a private reply that should go via netmail */
  307.                /* Create a message file in the netmail area with this info */
  308.                 *(holder1+totread) = '\0';
  309.                 ptr = holder1+totread;
  310.                 ++totread;
  311.                 while ((*ptr == '\0') || ((*ptr & 0x7f) == '\r') || ((*ptr & 0x7f) == '\n'))
  312.                     {
  313.                     --ptr;
  314.                     --totread;
  315.                     }
  316.                 /* Now check again if it is a null message */
  317.                 if (totread <= sizeof (MSG))
  318.                     {
  319.                     printf ("\r%s is a null message - continuing\n", fname);
  320.                      continue;
  321.                     }
  322.  
  323.                 msgl = totread - sizeof (MSG);
  324.                find_orig (totread);
  325.                if (!originl)
  326.                   {
  327.                     origin = originline;
  328.                     originl = strlen (originline);
  329.                   }
  330.                strcpy (tmpjunk, h->to);
  331.                /* Set the SENT bit in the message in the echomail area */
  332.                (void) fast_lseek (f, 0L, SEEK_SET);
  333.                     h->attr |= MSGSENT;
  334.                     (void) fast_write (f, (char *) h, sizeof(MSG));
  335.                     (void) fast_close (f);
  336.                 printf ("\r%s:%d.MSG -=> ", which->area_name, msg_nums[i]);
  337.                (void) write_reply (which);
  338.                printf (" Forwarded to %s\n", h->to);
  339.  
  340.                /* Get the original message and find the originating net/node */
  341.                done = 0;
  342.                while (!done)
  343.                   {
  344.                     sprintf (t1, "\\%d.MSG", h->reply);
  345.  
  346.                     /* Open the message file */
  347.                     if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  348.                         {
  349.                     printf ("\r%s could not open - continuing\n", fname);
  350.                     sprintf (fname1, "%s\\%d.MSG", config.mailpath, mail_high);
  351.                      unlink (fname1);
  352.                      --mail_high;
  353.                         continue;
  354.                         }
  355.  
  356.                     /* Read the whole thing in */
  357.                 if ((totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG))) <= (sizeof (MSG)))
  358.                         {
  359.                      (void) fast_close (f);
  360.                        printf ("\r%s is a null message - continuing\n", fname);
  361.                     sprintf (fname1, "%s\\%d.MSG", config.mailpath, mail_high);
  362.                      unlink (fname1);
  363.                      --mail_high;
  364.                         continue;
  365.                     }
  366.  
  367.                   (void) fast_close (f);
  368.                   if ((h->reply == 0) || (strcmp (h->from, tmpjunk) == 0))
  369.                      done = 1;
  370.                   }
  371.                if (strcmp (h->from, tmpjunk) != 0)
  372.                   {
  373.                   printf ("\r%s:%d.MSG No valid recipient message for private reply - sent regular echomail\n",
  374.                      which->area_name, msg_nums[i]);
  375.                 sprintf (fname1, "%s\\%d.MSG", config.mailpath, mail_high);
  376.                   unlink (fname1);
  377.                   --mail_high;
  378.                     sprintf (t1, "\\%d.MSG", msg_nums[i]);
  379.                     /* Open the message file */
  380.                     if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  381.                         {
  382.                         printf ("\r%s could not open - continuing\n", fname);
  383.                         continue;
  384.                         }
  385.  
  386.                     /* Read the whole thing in */
  387.                     totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG));
  388.                   goto reg_echo;
  389.                   }
  390.  
  391.                 find_orig(totread);
  392.  
  393.                if (originl == 0)
  394.                   {
  395.                   printf ("\r%s:%d.MSG No Origin for private reply - continuing\n",
  396.                      which->area_name, msg_nums[i]);
  397.                 sprintf (fname1, "%s\\%d.MSG", config.mailpath, mail_high);
  398.                   unlink (fname1);
  399.                   --mail_high;
  400.                     sprintf (t1, "\\%d.MSG", msg_nums[i]);
  401.                     /* Open the message file */
  402.                     if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  403.                         {
  404.                         printf ("\r%s could not open - continuing\n", fname);
  405.                         continue;
  406.                         }
  407.  
  408.                     /* Read the whole thing in */
  409.                     totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG));
  410.                   goto reg_echo;
  411.                   }
  412.  
  413.                new_zone = 0;
  414.                new_net = 0;
  415.                new_node = 0;
  416.                new_point = 0;
  417.  
  418.                s1 = origin+originl-1;
  419.                while ((s1 > origin) && (*s1 != '('))
  420.                   --s1;
  421.  
  422.                if (*s1 != '(')
  423.                   {
  424.                   printf ("\r%s:%d.MSG Cannot find original node for private reply - sent regular echomail\n",
  425.                      which->area_name, msg_nums[i]);
  426.                 sprintf (fname1, "%s\\%d.MSG", config.mailpath, mail_high);
  427.                   unlink (fname1);
  428.                   --mail_high;
  429.                     sprintf (t1, "\\%d.MSG", msg_nums[i]);
  430.                     /* Open the message file */
  431.                     if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  432.                         {
  433.                         printf ("\r%s could not open - continuing\n", fname);
  434.                         continue;
  435.                         }
  436.  
  437.                     /* Read the whole thing in */
  438.                     totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG));
  439.                   goto reg_echo;
  440.                   }
  441.  
  442.                while ((!isdigit (*s1)) && (s1 < origin+originl-1))
  443.                   ++s1;
  444.  
  445.                if (sscanf (s1, "%d:%d/%d.%d", &new_zone, &new_net, &new_node, &new_point) != 4)
  446.                   {
  447.                   new_zone = 0;
  448.                   new_net = 0;
  449.                   new_node = 0;
  450.                   if (sscanf (s1, "%d:%d/%d", &new_zone, &new_net, &new_node) != 3)
  451.                      {
  452.                      new_zone = 0;
  453.                      new_net = 0;
  454.                      if (sscanf (s1, "%d/%d.%d", &new_net, &new_node, &new_point) != 3)
  455.                         {
  456.                         new_net = 0;
  457.                         new_node = 0;
  458.                         if (sscanf (s1, "%d/%d", &new_net, &new_node) != 2)
  459.                            {
  460.                            printf ("\r%s:%d.MSG Cannot find original node for private reply - sent regular echomail\n",
  461.                               which->area_name, msg_nums[i]);
  462.                             sprintf (fname1, "%s\\%d.MSG", config.mailpath, mail_high);
  463.                            unlink (fname1);
  464.                            --mail_high;
  465.                            sprintf (t1, "\\%d.MSG", msg_nums[i]);
  466.                             /* Open the message file */
  467.                             if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  468.                                 {
  469.                                 printf ("\r%s could not open - continuing\n", fname);
  470.                             continue;
  471.                             }
  472.  
  473.                         /* Read the whole thing in */
  474.                           totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG));
  475.                            goto reg_echo;
  476.                            }
  477.                         }
  478.                      }
  479.                   }
  480.  
  481.                /* Change the destination net/node in the netmail message */
  482.                 sprintf (fname1, "%s\\%d.msg", config.mailpath, mail_high);
  483.  
  484.                 /* Open the message file */
  485.                 if((f = open (fname1, O_RDWR|O_BINARY)) == -1)
  486.                      {
  487.                     printf ("\r%s could not open - sent regular echomail\n", fname1);
  488.                   unlink (fname1);
  489.                   --mail_high;
  490.                     sprintf (t1, "\\%d.MSG", msg_nums[i]);
  491.                     /* Open the message file */
  492.                     if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  493.                         {
  494.                         printf ("\r%s could not open - continuing\n", fname);
  495.                         continue;
  496.                         }
  497.  
  498.                     /* Read the whole thing in */
  499.                     totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG));
  500.                   goto reg_echo;
  501.                     }
  502.  
  503.                 /* Read the whole thing in */
  504.                 if (fast_read (f, holder1, sizeof(MSG)) < (sizeof (MSG)))
  505.                      {
  506.                   (void) fast_close(f);
  507.                     printf ("\r%s is a null message - sent regular echomail\n", fname1);
  508.                   unlink (fname1);
  509.                   --mail_high;
  510.                     sprintf (t1, "\\%d.MSG", msg_nums[i]);
  511.                     /* Open the message file */
  512.                     if((f = open (fname, O_RDWR|O_BINARY)) == -1)
  513.                         {
  514.                         printf ("\r%s could not open - continuing\n", fname);
  515.                         continue;
  516.                         }
  517.  
  518.                     /* Read the whole thing in */
  519.                     totread = fast_read (f, holder1, NUMBLOCKS*1024+sizeof(MSG));
  520.                   goto reg_echo;
  521.                     }
  522.  
  523.                if ((new_zone == 0) ||
  524.                   (new_zone == (config.zone[1] == 0 ? 1 : config.zone[1])))
  525.                   {
  526.                   h->dest_net = new_net;
  527.                   h->dest = new_node;
  528.                   new_zone = 0;
  529.                   }
  530.                else
  531.                   {
  532.                   h->dest_net = (config.zone[1] == 0 ? 1 : config.zone[1]);
  533.                   h->dest     = new_zone;
  534.                   }
  535.  
  536.                h->reply = 0;
  537.                h->up = 0;
  538.                h->attr &= ~MSGSENT;
  539.                h->attr |= MSGKILL|MSGLOCAL;
  540.  
  541.                (void) fast_lseek (f, 0L, SEEK_SET);
  542.                (void) fast_write (f, (char *) h, sizeof (MSG));
  543.  
  544.                if (new_zone || (new_point > 0))
  545.                   {
  546.                   (void) fast_lseek (f, -3L, SEEK_END);
  547.                   if (new_zone)
  548.                      {
  549.                      sprintf (fname1, "\r\001INTL %d:%d/%d %d:%d/%d",
  550.                         new_zone, new_net, new_node,
  551.                         config.zone[1]?1:config.zone[1],config.net[1],
  552.                         config.node[1]);
  553.                      (void) fast_write (f, (char *) fname1, strlen (fname1));
  554.                      }
  555.                   if (new_point > 0)
  556.                      {
  557.                      sprintf (fname1, "\r\001TOPT %d", new_point);
  558.                      (void) fast_write (f, (char *) fname1, strlen (fname1));
  559.                      }
  560.                   fast_write (f, "\r\n\r\n", 5);
  561.                   }
  562.  
  563.                continue;
  564.                }
  565.             }
  566.          else if (noprivate)
  567.             {
  568.             continue;
  569.             }
  570.          }
  571.  
  572. reg_echo:
  573.         q1 = holder;
  574.         if (*q1 == 1)
  575.             {
  576.             ++q1;
  577.             }
  578.         while ((isspace ((*q1)&0x7f)) || (*q1 == 1))
  579.             ++q1;
  580.  
  581.         /* If we got here, then the header is fine, now try to find the rest */
  582.         if (((totread - sizeof(MSG)) >= 6) &&
  583.             (strncmp ("NOECHO", q1, 6) == 0))
  584.             {
  585.             printf ("\r%s is a NOECHO message - continuing\n", fname);
  586.             continue;
  587.             }
  588.  
  589.         *(holder1+totread) = '\0';
  590.         ptr = holder1+totread;
  591.         ++totread;
  592.         while ((*ptr == '\0') || ((*ptr & 0x7f) == '\r') || ((*ptr & 0x7f) == '\n'))
  593.             {
  594.             --ptr;
  595.             --totread;
  596.             }
  597.  
  598.         /* Now check again if it is a null message */
  599.         if (totread <= sizeof (MSG))
  600.             {
  601.             printf ("\r%s is a null message - continuing\n", fname);
  602.             continue;
  603.             }
  604.  
  605.         msgl = totread - sizeof (MSG);
  606.  
  607.         /* Get rid of any embedded null characters */
  608.         ptr = holder1 + sizeof (MSG);
  609.         l = 0;
  610.         while (l < msgl)
  611.         {
  612.           j = strlen (ptr);
  613.           l += j;
  614.         if (l < msgl)
  615.           {
  616.           ptr = ptr + j;
  617.           *ptr = ' ';
  618.           }
  619.       }
  620.  
  621.       if ((which->flags & ROUTETHRU) || (which->flags & MAIL_DIR))
  622.          {
  623.             /* If it is us, then continue on */
  624.             for (l = 1; l <= config.num_addrs; l++)
  625.                 {
  626.                 if (  (config.net[l] == h->dest_net)
  627.                      &&(config.node[l] == h->dest))
  628.                     {
  629.                     break;
  630.                     }
  631.                 }
  632.          if ((l <= config.num_addrs) ||
  633.              (h->attr & MSGFILE) ||
  634.              (h->attr & MSGFRQ) ||
  635.              (h->attr & MSGURQ) ||
  636.              (h->attr & MSGSENT))
  637.             {
  638.             continue;
  639.             }
  640.  
  641.          h->attr &= NO_CLEAR;
  642.          h->attr |= def_attr;
  643.  
  644.          if (notquiet)
  645.             printf ("\r%s:%04d.MSG -=> Node %4d/%-4d", which->area_name,
  646.                     msg_nums[i], h->dest_net, h->dest);
  647.  
  648.          originl = 0;
  649.          seen_byl = 0;
  650.          if (write_it (which, -1))
  651.             {
  652.             fast_close (f);
  653.             return (2);
  654.             }
  655.          if (which->flags & MAIL_DIR)
  656.             {
  657.             if ((h->attr & MSGKILL) || (h->attr & MSGFWD))
  658.                {
  659.                unlink (fname);
  660.                }
  661.             else
  662.                {
  663.                h->attr |= MSGSENT;
  664.                (void) fast_lseek (f, 0L, SEEK_SET);
  665.                (void) fast_write (f, (unsigned char *)h, sizeof (MSG));
  666.                }
  667.             }
  668.          continue;
  669.          }
  670.  
  671.         /* Now find the origin line */
  672.         find_orig(totread);
  673.  
  674.  
  675. #if DEBUG
  676. printf ("origin line is of length %d and it is\n", originl);
  677. if (originl > 0)
  678. {
  679. sprintf (fname1, "%%%d.%ds\n", originl, originl);
  680. printf (fname1, origin);
  681. }
  682. #endif
  683.  
  684.         /* Now find the seen-by's */
  685.         find_seen(totread);
  686.  
  687. #if DEBUG
  688. printf ("seen-by's are of length %d and they are\n", seen_byl);
  689. if (seen_byl>0)
  690. {
  691. sprintf (fname1, "%%%d.%ds\n", seen_byl, seen_byl);
  692. printf (fname1, seen_by);
  693. }
  694. #endif
  695.  
  696.         /* Do we have a valid message? */
  697.         if (seen_by != origin)
  698.             {
  699.             /* This is for a message that has been scanned already */
  700. #if DEBUG
  701. printf ("message %d has already been scanned\n", msg_nums[i]);
  702. #endif
  703.  
  704.             if (noforward)
  705.                 {
  706.                 continue;
  707.                 }
  708.  
  709.  
  710.             /* Get the seen-by list */
  711.             get_seen_bys (seen_by, seen_byl, SEENBYSTR, seen_nets, seen_nodes, &tot_seen);
  712.          /* Get the PATH: line */
  713.          if (do_path)
  714.             {
  715.             get_seen_bys (seen_by, seen_byl, PATHSTR, path_nets, path_nodes, &tot_path);
  716.             }
  717.  
  718. #if DEBUG
  719. printf ("%d SEEN-BYS:\n", tot_seen);
  720. for (j = 0; j < tot_seen; j++)
  721. printf ("%d/%d ", seen_nets[j], seen_nodes[j]);
  722. printf ("\n");
  723. #endif
  724.  
  725.             /* OK, now step through the nodes we process and if they are not */
  726.             /* in the seen-by list we mark it for future reference */
  727.             foo  = 0;
  728.             foo1 = 0;
  729.             for (j = 0; j < which->num_nodes; j++)
  730.                 {
  731.                 for (k = foo; k < tot_seen; k++)
  732.                     {
  733.                     if ((seen_nets[k] == which->net[j]) &&
  734.                          (seen_nodes[k] == which->node[j]))
  735.                         {
  736.                         foo = k + 1;
  737.                         break;
  738.                         }
  739.                     }
  740.                 if (k == tot_seen)
  741.                     {
  742.                     foo1++;
  743.                     not_seen[j] = 1;
  744.                     }
  745.                 else
  746.                     not_seen[j] = 0;
  747.                 }
  748.  
  749.             /* Did we add any nodes? */
  750.             if (foo1)
  751.                 {
  752.                 /* We did, so now add them to the seen-bys */
  753.                 for (j = 0; j < which->num_nodes; j++)
  754.                     {
  755.                     if (not_seen[j])
  756.                         {
  757.                         seen_nets[tot_seen] = which->net[j];
  758.                         seen_nodes[tot_seen] = which->node[j];
  759.                         ++tot_seen;
  760.                         }
  761.                     }
  762.  
  763.                 /* Re-sort the seen-bys */
  764.                 sort_em (seen_zones, seen_nets, seen_nodes, tot_seen, 0, 0, NULL);
  765.  
  766.                 /* Create the new seen-by list */
  767.                 create_seen (seen_by, seen_nets, seen_nodes, tot_seen, 1, SEENBYSTR);
  768.  
  769.             /* Put in the path if necessary */
  770.             if (do_path)
  771.                {
  772.                sbl = seen_byl;
  773.                if (tot_path > 0)
  774.                   {
  775.                   ctla = ctrla;
  776.                   ctrla = 1;
  777.                   create_seen (&(seen_by[seen_byl-2]), path_nets, path_nodes, tot_path, 1, PATHSTR);
  778.                   ctrla = ctla;
  779.                   seen_byl += sbl - 2;
  780.                   }
  781.                path_nets[tot_path] = config.net[1];
  782.                path_nodes[tot_path] = config.node[1];
  783.                ++tot_path;
  784.                }
  785.  
  786.                 /* If the new seen_by is less then the old, then we have */
  787.                 /* to delete the message and create it again so that the */
  788.                 /* end of the message is in the proper place */
  789. #ifndef VPURGE
  790.             if (!(which->flags & PASS_THRU))
  791. #else  /* VPURGE */
  792.             if (!((which->flags & PASS_THRU) || (which->flags & V_PURGE)))
  793. #endif /* VPURGE */
  794.                {
  795.                 if (stricmp (h->from, "sysop") == 0)
  796.                     {
  797.                   if (h->attr & MSGLOCAL)
  798.                      {
  799.                     strcpy (h->from, sysop_name);
  800.                      }
  801.                   else
  802.                      {
  803.                      /* Apparently we have a person trying to enter a message
  804.                         through the back door */
  805.                      sprintf (h->from, "Sysop (Apparently From %d/%d)", h->orig_net, h->orig);
  806.                      }
  807.                    }
  808.  
  809.                 if (seen_byl+originl+msgl+sizeof(MSG) < totread)
  810.                     {
  811. #if DEBUG
  812. printf ("special case where message is shorter\n");
  813. #endif
  814.                     /* Close the old handle */
  815.                     (void) fast_close (f);
  816.  
  817.                     /* Remove the file so we can start again */
  818.                        unlink (fname);
  819.  
  820.                     /* Reopen the file for writing */
  821.                     f = open (fname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE);
  822.  
  823.                     /* Write out the header and message stuff */
  824.                     (void) fast_write (f, (char *) h, sizeof(MSG)+msgl);
  825.                     }
  826.  
  827.                 /* Write out the new message into the proper area */
  828.                 write_msg (f);
  829.                }
  830.  
  831.             if (do_path)
  832.                {
  833.                ctla = ctrla;
  834.                ctrla = 1;
  835.                create_seen (&(seen_by[sbl-2]), path_nets, path_nodes, tot_path, 1, PATHSTR);
  836.                ctrla = ctla;
  837.                seen_byl += sbl - 2;
  838.                }
  839.  
  840.             /* Do we have tiny seen-bys? */
  841.                 if (tiny_seen)
  842.                     {
  843.                     create_seen (seen_by, &(which->net[0]),
  844.                         &(which->node[0]), which->num_nodes, 1, SEENBYSTR);
  845.  
  846.                if (do_path)
  847.                   {
  848.                   ctla = ctrla;
  849.                   sbl = seen_byl;
  850.                   ctrla = 1;
  851.                   create_seen (&(seen_by[seen_byl-2]), path_nets, path_nodes, tot_path, 1, PATHSTR);
  852.                   ctrla = ctla;
  853.                   seen_byl += sbl - 2;
  854.                   }
  855.                     }
  856.  
  857.             /* If we are dealing with a private net, new seen-bys */
  858.             if (priv_net)
  859.                {
  860.                 if (tiny_seen)
  861.                     {
  862.                     create_seen (seen_by, &(which->net[0]),
  863.                         &(which->node[0]), which->num_nodes, 0, SEENBYSTR);
  864.  
  865.                   if (do_path)
  866.                      {
  867.                      ctla = ctrla;
  868.                      sbl = seen_byl;
  869.                      ctrla = 1;
  870.                      create_seen (&(seen_by[seen_byl-2]), path_nets, path_nodes, tot_path, 1, PATHSTR);
  871.                      ctrla = ctla;
  872.                      seen_byl += sbl - 2;
  873.                      }
  874.                     }
  875.                 else
  876.                     {
  877.                     /* Create the new seen-by list */
  878.                     create_seen (seen_by, seen_nets, seen_nodes, tot_seen, 0, SEENBYSTR);
  879.  
  880.                   if (do_path)
  881.                      {
  882.                      ctla = ctrla;
  883.                      sbl = seen_byl;
  884.                      ctrla = 1;
  885.                      create_seen (&(seen_by[seen_byl-2]), path_nets, path_nodes, tot_path, 1, PATHSTR);
  886.                      ctrla = ctla;
  887.                      seen_byl += sbl - 2;
  888.                      }
  889.                   }
  890.                     }
  891.  
  892.                 /* Set up the message header for putting into netmail area */
  893.                 h->orig_net = config.net[1];
  894.                 h->orig = config.node[1];
  895.                 h->attr = (h->attr & MSGPRIVATE) | MSGKILL;
  896.                 h->reply = h->up = 0;
  897.  
  898.                 /* For each node not yet scanned, write out the message */
  899.                 for (j = 0; j < which->num_nodes; j++)
  900.                     {
  901.                     if (not_seen[j])
  902.                         {
  903.                         /* If it is us, then continue on */
  904.                         for (l = 1; l <= config.num_addrs; l++)
  905.                             {
  906.                             if (  (config.net[l] == which->net[j])
  907.                                  &&(config.node[l] == which->node[j]))
  908.                                 {
  909.                                 break;
  910.                                 }
  911.                             }
  912.  
  913.                         /* Was it to us? */
  914.                         if (l <= config.num_addrs)
  915.                             continue;
  916.  
  917.                   if (num_zone &&
  918.                      (zone_net[0] == which->net[j]) &&
  919.                      (zone_node[0] == which->node[j]))
  920.                      {
  921.                      create_seen (seen_by, &(zone_net[1]), &(zone_node[1]), num_zone-1, 0, SEENBYSTR);
  922.  
  923.                      if (do_path)
  924.                         {
  925.                         ctla = ctrla;
  926.                         sbl = seen_byl;
  927.                         ctrla = 1;
  928.                         create_seen (&(seen_by[seen_byl-2]), path_nets, path_nodes, tot_path, 1, PATHSTR);
  929.                         ctrla = ctla;
  930.                         seen_byl += sbl - 2;
  931.                         }
  932.                      }
  933.  
  934.                   if (notquiet)
  935.                         printf ("\r%s:%04d.MSG -=> Node %4d/%-4d", which->area_name,
  936.                             msg_nums[i], which->net[j], which->node[j]);
  937.  
  938.                   if ((which->flags & PARENT) && (last_name != which->aname[j]))
  939.                      {
  940.                      last_name = which->aname[j];
  941.                      /* Set up the area name */
  942.                      if (ctrla)
  943.                          {
  944.                          sprintf (arealine, "\001AREA: %s\r", which->aname[j]);
  945.                          }
  946.                      else
  947.                          {
  948.                          sprintf (arealine, "AREA:%s\r", which->aname[j]);
  949.                          }
  950.                      areal = strlen (arealine);
  951.                      }
  952.  
  953.                   if (write_it (which, j))
  954.                       {
  955.                       /* Now set the high water mark for next time */
  956.                       set_hw (msg_nums[i-1], which);
  957.  
  958.                       return (2);
  959.                       }
  960.  
  961.                   #if STATS
  962.                       which->msgs_scanned[j]++;
  963.                   #endif
  964.  
  965.                   if (num_zone &&
  966.                      (zone_net[0] == which->net[j]) &&
  967.                      (zone_node[0] == which->node[j]))
  968.                      {
  969.                         if (tiny_seen)
  970.                             {
  971.                             create_seen (seen_by, &(which->net[0]),
  972.                                 &(which->node[0]), which->num_nodes, 1, SEENBYSTR);
  973.                             }
  974.  
  975.                      /* If we are dealing with a private net, new seen-bys */
  976.                      if (priv_net)
  977.                         {
  978.                             if (tiny_seen)
  979.                             {
  980.                             create_seen (seen_by, &(which->net[0]),
  981.                                     &(which->node[0]), which->num_nodes, 0, SEENBYSTR);
  982.                             }
  983.                         else
  984.                             {
  985.                                 /* Create the new seen-by list */
  986.                              create_seen (seen_by, seen_nets, seen_nodes, tot_seen, 0, SEENBYSTR);
  987.                            }
  988.                             }
  989.                      else
  990.                         {
  991.                          create_seen (seen_by, seen_nets, seen_nodes, tot_seen, 1, SEENBYSTR);
  992.                         }
  993.                      }
  994.                         }
  995.                     }
  996.                 }
  997.             }
  998.         else
  999.             {
  1000.             /* It appears that this message has not yet been scanned */
  1001. #if DEBUG
  1002. printf ("message %d has not yet been scanned\n", msg_nums[i]);
  1003. #endif
  1004.             /* No origin line, point at ours */
  1005.             if (!originl)
  1006.                 {
  1007.                 origin = originline;
  1008.                 originl = strlen (originline);
  1009.                 }
  1010.  
  1011.             /* Point at our seen-bys */
  1012.             seen_by = seen_byline;
  1013.             seen_byl = strlen (seen_byline);
  1014.  
  1015.             /* If the new seen_by is less then the old, then we have */
  1016.             /* to delete the message and create it again so that the */
  1017.             /* end of the message is in the proper place */
  1018. #ifndef VPURGE
  1019.          if (!(which->flags & PASS_THRU))
  1020. #else  /* VPURGE */
  1021.          if (!((which->flags & PASS_THRU) || (which->flags & V_PURGE)))
  1022. #endif /* VPURGE */
  1023.             {
  1024.             if (h->attr & MSGLOCAL)
  1025.                {
  1026.                 if (stricmp (h->from, "sysop") == 0)
  1027.                   {
  1028.                 strcpy (h->from, sysop_name);
  1029.                   }
  1030.                }
  1031.             else
  1032.                {
  1033.                /* Apparently we have a person trying to enter a message
  1034.                   through the back door */
  1035.                sprintf (&(sysop_name[50]), "%s Of %d/%d", h->from,
  1036.                   h->orig_net, h->orig);
  1037.                strncpy (h->from, &(sysop_name[50]), 35);
  1038.                h->from[35] = '\0';
  1039.                }
  1040.  
  1041.             if (seen_byl+originl+msgl+sizeof(MSG) < totread)
  1042.                 {
  1043.                 /* Close the old handle */
  1044.                 (void) fast_close (f);
  1045.  
  1046.                    /* Remove the file so we can start again */
  1047.                 unlink (fname);
  1048.  
  1049.                 /* Reopen the file for writing */
  1050.                 f = open (fname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE);
  1051.  
  1052.                 /* Write out the header and message stuff */
  1053.                    (void) fast_write (f, (char *) h, sizeof(MSG)+msgl);
  1054.                 }
  1055.  
  1056.             /* Write back the message with new seen-bys etc */
  1057.             write_msg (f);
  1058.          }
  1059.  
  1060.          /* If we have a private network, new seen-by's */
  1061.          if (priv_net)
  1062.             {
  1063.             create_seen(&seen_byline[1], &(which->net[0]), &(which->node[0]),
  1064.                 which->num_nodes, 0, SEENBYSTR);
  1065.  
  1066.             if (do_path)
  1067.                {
  1068.                seen_byl = strlen (seen_byline);
  1069.                sprintf (&(seen_byline[seen_byl-2]), "\001PATH: %d/%d\r\n\r\n",
  1070.                   config.net[1], config.node[1]);
  1071.                seen_byl = strlen (seen_byline);
  1072.                }
  1073.             }
  1074.  
  1075.          /* Set up the message header for putting into netmail area */
  1076.             h->orig_net = config.net[1];
  1077.             h->orig = config.node[1];
  1078.             h->attr = (h->attr & MSGPRIVATE) | MSGKILL;
  1079.             h->reply = h->up = 0;
  1080.  
  1081.             /* Now write out the message for each node that has not seen it */
  1082.             for (j = 0; j < which->num_nodes; j++)
  1083.                 {
  1084.                 /* If it is us, then continue on */
  1085.                 for (l = 1; l <= config.num_addrs; l++)
  1086.                     {
  1087.                     if (  (config.net[l] == which->net[j])
  1088.                          &&(config.node[l] == which->node[j]))
  1089.                         {
  1090.                         break;
  1091.                         }
  1092.                     }
  1093.  
  1094.                 /* Was it to us? */
  1095.                 if (l <= config.num_addrs)
  1096.                     continue;
  1097.  
  1098.             if (num_zone &&
  1099.                (zone_net[0] == which->net[j]) &&
  1100.                (zone_node[0] == which->node[j]))
  1101.                {
  1102.                create_seen (&seen_byline[1], &(zone_net[1]), &(zone_node[1]), num_zone-1, 0, SEENBYSTR);
  1103.  
  1104.                if (do_path)
  1105.                   {
  1106.                   seen_byl = strlen (seen_byline);
  1107.                   sprintf (&(seen_byline[seen_byl-2]), "\001PATH: %d/%d\r\n\r\n",
  1108.                      config.net[1], config.node[1]);
  1109.                   seen_byl = strlen (seen_byline);
  1110.                   }
  1111.                }
  1112.  
  1113.             if (notquiet)
  1114.                 printf ("\r%s:%04d.MSG -=> Node %4d/%-4d", which->area_name,
  1115.                     msg_nums[i], which->net[j], which->node[j]);
  1116.  
  1117.             /* Change the name if necessary */
  1118.             if ((which->flags & PARENT) && (last_name != which->aname[j]))
  1119.                {
  1120.                last_name = which->aname[j];
  1121.                /* Set up the area name */
  1122.                if (ctrla)
  1123.                    {
  1124.                    sprintf (arealine, "\001AREA: %s\r", which->aname[j]);
  1125.                    }
  1126.                else
  1127.                    {
  1128.                    sprintf (arealine, "AREA:%s\r", which->aname[j]);
  1129.                    }
  1130.                areal = strlen (arealine);
  1131.                }
  1132.  
  1133.              if (write_it (which, j))
  1134.                 {
  1135.                 /* Now set the high water mark for next time */
  1136.                 set_hw (msg_nums[i-1], which);
  1137.  
  1138.                 return (2);
  1139.                 }
  1140.  
  1141.              #if STATS
  1142.                  which->msgs_scanned[j]++;
  1143.              #endif
  1144.  
  1145.             if (num_zone &&
  1146.                (zone_net[0] == which->net[j]) &&
  1147.                (zone_node[0] == which->node[j]))
  1148.                {
  1149.                if (priv_net)
  1150.                   {
  1151.                   create_seen(&seen_byline[1], &(which->net[0]), &(which->node[0]),
  1152.                     which->num_nodes, 0, SEENBYSTR);
  1153.                   }
  1154.                else
  1155.                   {
  1156.                     create_seen(&seen_byline[1], &(which->net[0]), &(which->node[0]),
  1157.                         which->num_nodes, 1, SEENBYSTR);
  1158.                   }
  1159.                }
  1160.                 }
  1161.             }
  1162.         }
  1163.  
  1164.     /* Close the files */
  1165.     if (f>0)
  1166.         (void) fast_close (f);
  1167.  
  1168.     /* Now set the high water mark for next time */
  1169.     set_hw (msg_nums[i-1], which);
  1170.  
  1171.     /* Output a newline if we did any messages */
  1172.     if (foo3 != msgs_done)
  1173.         putchar('\n');
  1174.  
  1175.     #if STATS
  1176.         LogScanNodes(which);
  1177.     #endif
  1178.  
  1179.     if (msgs_done >= max_msgs)
  1180.         {
  1181.         printf ("\nMaximum message count exceeded - exiting\n");
  1182.         return (1);
  1183.         }
  1184.  
  1185. #ifdef VPURGE
  1186.  
  1187. #if DEBUG
  1188.      printf ("V_Purge is still '%s'\n", (which->flags & V_PURGE)?("ON"):("OFF"));
  1189. #endif
  1190.  
  1191.      if (which->flags & V_PURGE)
  1192.         {
  1193.         for (i = 0; i < last_msg; i++)
  1194.            {
  1195.            sprintf (t1, "\\%d.MSG", msg_nums[i]);
  1196.            unlink(fname);
  1197.            }
  1198.         set_hw (1, which);
  1199.         }
  1200. #endif /* VPURGE */
  1201.  
  1202.     return (0);
  1203. }
  1204.  
  1205. 
  1206.