home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / berm122s / scan.c < prev    next >
C/C++ Source or Header  |  1993-08-16  |  55KB  |  1,941 lines

  1. /***************************************************************************
  2.  *  SCAN.C                                                                 *
  3.  *                                                                         *
  4.  *  echomail SCAN utility.                                                 *
  5.  *                                                                         *
  6.  * SCAN is part of the BERMUDA software. BERMUDA is a package of FidoNet   *
  7.  * compatible message/nodelist processing software.                        *
  8.  * Please read LICENSE for information about distribution.                 *
  9.  *                                                                         *
  10.  * Written by Jac Kersing,                                                 *
  11.  * Modifications by Enno Borgsteede and Rinaldo Visscher                   *
  12.  * Modifications by Vincent Pomey and Franck Arnaud                        *
  13.  ***************************************************************************/
  14.  
  15. /***************************************************************************
  16.  **
  17.  ** Update history:
  18.  **
  19.  ** Till version 0.63:
  20.  **  Conversion of comscan from CP/M to Atari ST.
  21.  ** 
  22.  ** Version 0.63: (release 01/19/89, TB 1.15)
  23.  ** - The maximum day limit has been changed. From 100 days to infinite.
  24.  **
  25.  ** Version 0.64:
  26.  ** - Aka, NODE and BOSS nodes removed. All addresses are ADDRESS.
  27.  ** - Added smart scanning (uses key).
  28.  ** - Added zones and points for message creation
  29.  **
  30.  ** Version 1.00 TB:
  31.  ** - Fixed control-file problem.
  32.  ** - Changed tearline to ComScan vx.xx TB/nn.
  33.  **
  34.  ** Version 1.01 TB:
  35.  ** - Adapted for Mark Williams C
  36.  **
  37.  ** Version 1.02 TB/ST by Enno F. Borgsteede
  38.  ** - Adapted for Turbo C/ST 2.0
  39.  **    - Error in point readressing fixed
  40.  ** - First tries to open .WM then .NM
  41.  **
  42.  ** Version 1.00 BERMUDA SCAN
  43.  ** - Adapted COMSCAN to SCAN
  44.  **************************************************************************/
  45.  
  46. /*
  47. #pragma warn -sus
  48. #pragma warn -par
  49. */
  50.  
  51. #define MAILER              /* needed in PANDORA.H */
  52.  
  53. #include "pandora.h"        /* for structure of the area's etc. */
  54. #include "mail.h"
  55.  
  56. #if TC
  57. #include <dos.h>
  58. #include <sys\stat.h>
  59. #endif
  60.  
  61. #include "scan.pro"
  62. #include "utextra.pro"
  63.  
  64. #define UVERSION "1.22"     /* Version number of this utility */
  65. #define LASTMOD  __DATE__
  66. #define isBERMUDA       0xA0
  67.  
  68. #define DEBUG   0              /* Display extended (debugging) info? */
  69.  
  70. #define MSGSCANNED      0x8000
  71.  
  72. /*  defines for readmessage         */
  73. #define ENDOFAREA   0       /* no more messages in area */
  74. #define SKIP        1       /* skip this message        */
  75. #define MSGALRIGHT  2       /* message ok               */
  76.  
  77. /* defines for writemessage         */
  78. #define OUTBOUND    0       /* message to mailarea      */
  79. #define LOCAL       1       /* message to local msgfile */
  80. #define SCANFILE    2       /* message to node file     */
  81.  
  82. /* defines for SEEN-BY treatement   */
  83. #define NOTHING     0       /* no echomail message         */
  84. #define POINTS      1       /* add pointlist to message    */
  85. #define LOCALS      2       /* add local list to msg       */
  86. #define DIFFZONE    4       /* add list for OTHER zone     */
  87. #define OTHERS      8       /* add all nodes already there */
  88.  
  89. struct _passw           /* structure for passwords */
  90. {
  91.   char passw[8];        /* the password itself */
  92.   int  zone;            /* zone number for remote */
  93.   int  net;             /* net number for remote */
  94.   int  node;            /* node number for remote */
  95.   int  point;           /* point number for remote */
  96.   int  my_aka;          /* the number in the addresslist for this sucker */
  97.   struct _passw *next;  /* pointer to next struct */
  98. } ;
  99.  
  100. struct _aka
  101. {
  102.  int zone;
  103.  int net;
  104.  int node;
  105.  int point;
  106.  int pointnet;
  107. } ;
  108.  
  109. void Aopen(), Aclose(), cleanEcho(), renumber();
  110.  
  111. /* Definitions of global variables first */
  112.  
  113. char progname[]="B-S";      /* program name for logging             */
  114. char *Bpath="";             /* path for config file                 */
  115.  
  116. char *AreaPath[N_AREAS];    /* path to message area                 */
  117. char *AreaName[N_AREAS];    /* name of area                         */
  118. char *AreaOrig[N_AREAS];    /* the origin line for this area        */
  119. int  *ToZone[N_AREAS];      /* Zone, Net,                           */
  120. int  *ToNet[N_AREAS];       /*            Node and Point            */
  121. int  *ToNode[N_AREAS];      /*    numbers of nodes we're supposed   */
  122. int  *ToPoint[N_AREAS];     /*    to echo messages to..........     */
  123. int  SendTo[50];            /* Send to this node too?               */
  124. int  TZone[50];             /* Temp. storage for addresses          */
  125. int  TNet[50];              /* Zone and Net..                       */
  126. int  TNode[50];             /*               Node                   */
  127. int  TPoint[50];            /*                      Point           */
  128.  
  129. int  SeenZone[450];         /* Zone...                              */
  130. int  SeenNet[450];          /* adress of nodes that have seen       */
  131. int  SeenNode[450];         /*                         this message */
  132. int  SeenPoint[450];        /*                               Point  */
  133. int  nSeen;                 /* number of Seen-bys                   */
  134. int  PathZone[100];         /* Zone of path..                       */
  135. int  PathNet[100];          /* adresses listed in the               */
  136. int  PathNode[100];         /*                        path line     */
  137. int  PathPoint[100];        /* Ditto                                */
  138. int  nPath;                 /* number of nodes in Path              */
  139. char ThisArea[80];          /* name of this echomail area           */
  140.  
  141. int  OriginZone;            /* Address this message was created     */
  142. int  OriginNet;             /* Zone and Net                         */
  143. int  OriginNode;            /*              Node                    */
  144. int  OriginPoint;           /*                  Point               */
  145.  
  146. int  mailarea;              /* number of mailarea                   */
  147. int  msgareas;              /* number of messageareas               */
  148. char *hold;                 /* path to hold area                    */
  149. #ifdef LINN
  150. char *holdbink;
  151. #endif
  152. char *mailpath;             /* path to mailmsgs                     */
  153. char *netpath;              /* path to netmail                      */
  154. struct _aka alias[30];      /* aliases                              */
  155. int  nalias;                /* number of aliases                    */
  156. #ifdef LINN
  157. int  add_aka=0;             /* number of aliases to add to seen-bys */
  158. int  no_intl=0;
  159. int  binkley=0;
  160. #else
  161. int  add_aka;               /* number of aliases to add to seen-bys */
  162. #endif
  163. int  verbose=6;             /* level for message displaying         */
  164. int  loglevel;              /* level for message logging            */
  165. char *logname;              /* name of logfile                      */
  166. FILE *log;                  /* filepointer for logfile              */
  167. struct _passw *pwd;         /* password pointer                     */
  168.  
  169. char *ourorigin;            /* line for origin                      */
  170. int  ourzone;               /* zone,                                */
  171. int  ournet;                /*      net and                         */
  172. int  ournode;               /*              node of our BBS         */
  173. int  ourpoint;              /*                 point                */
  174. int  ourpointnet;           /* we've got a pointnet too             */
  175. char ourpwd[10];            /* the password we're using now         */
  176.  
  177. char *MESSAGE;              /* adress of message buffer (malloced)  */
  178. char *mend;                 /* points to end of the message         */
  179. char *endbody;              /* end of message body WITHOUT seen-bys */
  180. int  mlength;               /* length of message (including seen-by)*/
  181. int  area;                  /* area we're processing                */
  182. int  echomsgs;              /* number of echomsgs created           */
  183. char *origl;                /* points to origin line in message     */
  184. int  use_path;              /* do we wanna use the PATH line?       */
  185. int  use_kludge;            /* we want to use the IFNA kludge?      */
  186. int  use_origin;            /* do we wanna have an origin line??    */
  187. int  use_readdress;         /* readress message (fake from our bbs) */
  188. int  use_packet;            /* scan messages to packets             */
  189. int  use_tiny=0;            /* tiny adresses (ones I'm sending to)  */
  190. int  maxmsgs=1000;          /* max number of echomail messages      */
  191.  
  192. FILE *HDR;                  /* File pointers for message and header */
  193. FILE *MSG;                  /* files used in creating echomail and  */
  194. FILE *MHDR;                 /* updating the message file            */
  195. FILE *MMSG;
  196.  
  197. char oldmsg[80];            /* names of the message and header files */
  198. char oldhdr[80];
  199.  
  200. int  x;                     /* x position in line                   */
  201.  
  202. struct Hdr hdr;             /* storage for message header           */
  203. struct Hdr Mhdr;            /* storage for outgoing message header  */
  204.  
  205. int  pktzone;               /* zone, net, node and point            */
  206. int  pktnet;                /* = 4-D address for open packet        */
  207. int  pktnode;               /* used for saving messages to          */
  208. int  pktpoint;
  209. int  pktfake;               /* this is the fakenet we use           */
  210. FILE *pktfile;              /* the packet                           */
  211.  
  212. /* Ok, so far all definitions. The program is next.. */
  213.  
  214. void *myalloc(sp)
  215. size_t sp;
  216. {
  217.     char *tmp;
  218.     
  219.     tmp=malloc(sp);
  220.     if (tmp==NULL)
  221.     {
  222.         message(6,"!Mem error");
  223.         exit(1);
  224.     }
  225.     return tmp;
  226. }
  227.  
  228. char *skip_blanks(string)
  229. char *string;
  230. {
  231.     while (*string && isspace(*string)) ++string;
  232.     return string;
  233. }
  234.  
  235. char *skip_to_blank(string)
  236. char *string;
  237. {
  238.         while (*string && !isspace(*string)) ++string;
  239.         return string;
  240. }
  241.  
  242. char *ctl_string(string)
  243. char *string;
  244. {
  245.     char *p, *d;
  246.     p=skip_blanks(string);
  247.     d=malloc(strlen(p)+1);
  248.     if(d==NULL)
  249.     {
  250.         message(6,"!Mem error");
  251.         return "";
  252.     }
  253.     strcpy(d,p);
  254.     return d;
  255. }
  256.  
  257. char *ctl_path(string)
  258. char *string;
  259. {
  260.     char *p, *d, db[80];
  261.  
  262.     p=skip_blanks(string);
  263.     d=skip_to_blank(string);
  264.     *d='\0';
  265.     if (strlen(p)>78)
  266.     {
  267.         message(6,"!Path too long (%s)",p);
  268.         return "";
  269.     }
  270.     strcpy(db,p);
  271. #if UNIX
  272.     if (db[strlen(db)-1]!='/') strcat(db,"/");
  273. #else
  274.     if (db[strlen(db)-1]!='\\') strcat(db,"\\");
  275. #endif
  276.     return ctl_string(db);
  277. }
  278.  
  279. init_conf()
  280. {
  281.     FILE *conf;                     /* filepointer for config-file */
  282.     char buffer[256];               /* buffer for 1 line */
  283.     char *p;                        /* workhorse */
  284.     int count;                      /* just a counter... */
  285.     char *ffirst();                 /* directory find */
  286.     char *getenv();                 /* get the environment string */
  287.  
  288.     p=getenv("MAILER");
  289.     if (!ffirst("bermuda.cfg") &&      /* check local config */
  290.         !ffirst("tb.cfg") &&
  291.         p!=NULL && *p!='\0')
  292.     {                                   /* no local, and envi contained one */
  293.         Bpath= ctl_path(p);
  294.     }
  295.  
  296.     sprintf( buffer, "%sbermuda.cfg", Bpath);
  297.     conf= fopen(buffer, "r");
  298.  
  299.     if (conf==NULL)
  300.     {
  301.         sprintf(buffer,"%stb.cfg", Bpath);
  302.  
  303.         conf = fopen(buffer, "r");
  304.     }
  305.  
  306.     if (conf==NULL)   /* open config-file */
  307.     {
  308.         message(6,"!Configuration file not found, please check!!!");
  309.         return 1;                           /* not found, back */
  310.     }
  311.  
  312.     /* set all to default values */
  313.     
  314.     loglevel=255;
  315.     ourzone=ournet=ournode=0;
  316.     message(-1,"+Parsing configuration file");
  317.        
  318.     while((fgets(buffer, 250, conf)))       /* read a line */
  319.     {
  320.         p=skip_blanks(buffer);
  321.         if (*p==';') continue;               /* comment?? */
  322.  
  323.         /* delete ALL chars following (and inclusive) comment sign */
  324.         if ((p=strchr(buffer,';'))!=NULL)  *p= '\0';
  325.         if ((count= (int)strlen(buffer))<3) continue;
  326.                                             /* what's the length of the rest? */
  327.         p= &buffer[--count];
  328.         if (*p=='\n') *p=0;                 /* delete (possible) newline char */
  329.  
  330. #ifdef LINN
  331.         /* process "application bermuda" lines as normal lines */
  332.         if (!strnicmp(buffer,"application",11))
  333.         {
  334.             p=skip_blanks(&buffer[11]);
  335.             if(!strnicmp(p,"bermuda",7)) {
  336.                 p=skip_blanks(&p[7]);
  337.                 strcpy(buffer,p);
  338.             }
  339.         }
  340. #endif
  341.  
  342.         if (!strnicmp(buffer,"address",7))
  343.         {
  344.             p=skip_blanks(&buffer[7]);
  345.             if(getaddress(p,&alias[nalias].zone, &alias[nalias].net,
  346.                 &alias[nalias].node, &alias[nalias].point)!=7)
  347.             {
  348.                message(3,"!Invalid address in %s",buffer);
  349.                continue;
  350.             }
  351.             p=skip_blanks(skip_to_blank(p));
  352.  
  353.             if (*p=='+' || *p=='*') p=skip_blanks(skip_to_blank(p));
  354.  
  355.             if (*p && isdigit(*p))
  356.             {
  357.                 if ((alias[nalias].pointnet=atoi(p))==0)
  358.                 {
  359.                    message(6,"!Invalid pointnet in %s",buffer);
  360.                    continue;
  361.                 }
  362.             }
  363.             else alias[nalias].pointnet=0;
  364.             ++nalias;
  365.  
  366.             ourzone=alias[0].zone;
  367.             ournet=alias[0].net;
  368.             ournode=alias[0].node;
  369.             ourpoint=alias[0].point;
  370.             ourpointnet=alias[0].pointnet;
  371.  
  372.             continue;
  373.         }
  374.  
  375.         if (!strnicmp(buffer,"loglevel",8))
  376.         {
  377.             p=skip_blanks(&buffer[8]);
  378.             if (sscanf(p,"%d", &count)!=1 || count>6 || count<0)
  379.                 message(3,"-Invalid loglevel (%s)", p);
  380.             else loglevel=count;
  381.             continue;
  382.         }
  383.  
  384.         if (!strnicmp(buffer, "statuslog",9))
  385.         {
  386.             logname= ctl_string(&buffer[9]);
  387.             if ((log=fopen(logname, "a"))==NULL)
  388.                 if ((log=fopen(logname, "w+"))==NULL)
  389.                 {
  390.                     message(6,"!Could not create logfile!");
  391.                     free(logname);
  392.                     logname=NULL;
  393.                 }
  394.             else
  395.             {
  396.                 fflush(log);
  397.             }
  398.             continue;
  399.         }
  400.  
  401.         if (!strnicmp(buffer,"netfile",7))
  402.         {
  403.             mailpath=ctl_path(&buffer[7]);
  404.             continue;
  405.         }
  406.  
  407.         if (!strnicmp(buffer,"netmail",7))
  408.         {
  409.             netpath=ctl_string(&buffer[7]);
  410.             continue;
  411.         }
  412.  
  413.         if (!strnicmp(buffer,"hold",4))
  414.         {
  415.             hold=ctl_path(&buffer[4]);
  416. #ifdef LINN
  417.             holdbink=strdup(hold); holdbink[strlen(holdbink)-1]=0;
  418. #endif
  419.             continue;
  420.         }
  421.  
  422.         if (!strnicmp(buffer,"key",3))
  423.         {
  424.             parsekey(&buffer[3]);
  425.             continue;
  426.         }
  427.  
  428. #ifdef LINN
  429.     if (!strnicmp(buffer,"binkley", 7))
  430.     {
  431.         binkley=1;
  432.         continue;
  433.     }
  434. #endif
  435.  
  436.     }
  437.     
  438.     fclose(conf);
  439.     
  440.     return 0;                           /* signal OK */
  441. }
  442.  
  443. void parsekey(p)
  444. char *p;
  445. {
  446.     int i;
  447.     char password[9];
  448.     struct _passw *pw,*pn;
  449.     int zone,net,node,point;
  450.     int my_aka=0;
  451.     
  452.     /* get to the end of the list. */
  453.     pw=pwd;
  454.     while (pw->next!=NULL) pw=pw->next;
  455.  
  456.     password[0]='\0';
  457.     
  458.     p=skip_blanks(p);
  459.     while (*p && *p!=';')
  460.     {
  461.         if (*p=='!')
  462.         {
  463.             strncpy(password,p+1,7);
  464.             for (i=0; i<7; ++i)
  465.             {
  466.                 if (isspace(password[i])) break;
  467.             }
  468.             password[i]='\0';
  469.  
  470.             /* skip password and go on to node(s) */
  471.             p=skip_to_blank(p);
  472.             p=skip_blanks(p);
  473.             continue;
  474.         }
  475.  
  476.         if (*p=='#')
  477.         {
  478.             if (getaddress(p+1,&zone,&net,&node,&point))
  479.             {
  480.                 int found=0;
  481.                 for (i=0; i<nalias; i++)
  482.                 {
  483.                     if (alias[i].zone==zone && alias[i].net==net &&
  484.                         alias[i].node==node && alias[i].point==point)
  485.                     {
  486.                         found++;
  487.                         break;
  488.                     }
  489.                 }
  490.                 if (found) my_aka=i;
  491.                 else
  492.                 {
  493.                     my_aka=0;
  494.                     message(3,"-Address %d:%d/%d.%d used in key is unknown",
  495.                      zone,net,node,point);
  496.                 }
  497.             }
  498.  
  499.             p= skip_to_blank(p);
  500.             p= skip_blanks(p);
  501.             continue;
  502.         }
  503.  
  504.         pn=pw->next= (struct _passw *) myalloc(sizeof(struct _passw));
  505.  
  506.         if (!getaddress(p,&zone,&net,&node,&point))
  507.         {
  508.             free(pn);
  509.             pw->next=NULL;
  510.             message(3,"-Invalid address: %s",p);
  511.             return;
  512.         }
  513.  
  514. #ifdef LINN /* as in pack */
  515.         if (point)
  516.         {
  517.             for (i=0; i < nalias; i++)
  518.             {
  519.                 if (alias[i].zone==zone && alias[i].net==net &&
  520.                     alias[i].node==node)
  521.                 {
  522.                     net= alias[i].pointnet;
  523.                     node= point;
  524.                     point= 0;
  525.                     break;
  526.                 }
  527.             }
  528.         }
  529. #endif
  530.  
  531.         pn->zone=zone;
  532.         pn->net=net;
  533.         pn->node=node;
  534.         pn->point=point;
  535.         pn->my_aka=my_aka;
  536.         strcpy(pn->passw,password);
  537.         p=skip_to_blank(p);
  538.         p=skip_blanks(p);
  539.         pw=pn;
  540.         pw->next=NULL;
  541.     }
  542.     
  543.     return;
  544. }
  545.  
  546. int getint(p,i)                                   /* Mind the calling parms! */
  547. char **p;
  548. int *i;
  549. {
  550.         char *q;
  551.         long temp;
  552.  
  553.         q=*p;
  554.         if (!isdigit(*q)) return (-1);
  555.  
  556.         temp=0;
  557.         do {
  558.            temp*=10;
  559.            temp+=(*q++-'0');
  560.            } while (isdigit(*q));
  561.         if (temp>32767) return (-1);
  562.         *p=q; *i=(int)temp;
  563.         return (0);
  564. }
  565.  
  566. int getaddress(str, zone, net, node, point)     /* Decode zz:nn/mm.pp number */
  567. char *str;       /* 0=error | 1=node | 2=net/node | 3=zone:net/node | 4=pnt */
  568. int *zone, *net, *node, *point;
  569. {
  570.         int retcode=0;
  571.  
  572.         *zone  = alias[0].zone;
  573.         *net   = alias[0].net;
  574.         *node  = alias[0].node;
  575.         *point = 0;
  576.  
  577.         str=skip_blanks(str);
  578.  
  579.         if (*str=='.') goto pnt;
  580.         retcode++;
  581.         if (getint(&str,node))
  582.         {
  583.             if (strnicmp(str,"ALL",3)) return (0);
  584.             *zone=*net=*node=-1;
  585.             return 10;
  586.         }
  587.         if (!*str) return (retcode);
  588.         if (*str=='.') goto pnt;
  589.         retcode++;
  590.         if (*str==':') {
  591.            str++;
  592.            *zone=*node;
  593.            *node=-1;
  594.            if (!*str) return (0);
  595.            if (getint(&str,node))
  596.            {
  597.               if (strnicmp(str,"ALL",3)) return (0);
  598.               *net=*node=-1;
  599.               return 10;
  600.            }
  601.            retcode++;
  602.         }
  603.         if (*str!='/') return (0);
  604.         str++;
  605.         *net=*node;
  606.         *node=alias[0].node;
  607.         if (getint(&str,node))
  608.         {
  609.             if (strnicmp(str,"ALL",3)) return (0);
  610.             *node=-1;
  611.             return 10;
  612.         }
  613.         if (*str=='.') goto pnt;
  614.         return (retcode);
  615. pnt:    str++;
  616.         if (getint(&str,point))
  617.         {
  618.             if (strnicmp(str,"ALL",3)) return (0);
  619.             *point=-1;
  620.             return 10;
  621.         }
  622.         return (4+retcode);
  623. }
  624.  
  625. getalias(zone,net,node,point)
  626. int zone,net,node,point;
  627. {
  628.     struct _passw *pw;
  629. #ifdef LINN
  630.     int i;
  631. #endif
  632.         
  633.     pw=pwd->next;
  634.  
  635. #ifdef LINN /* as in pack */
  636.     if (point)
  637.     {
  638.         for (i=0; i < nalias; i++)
  639.         {
  640.             if (alias[i].zone==zone && alias[i].net==net &&
  641.                alias[i].node==node && alias[i].point==0)
  642.             {
  643.                 net= alias[i].pointnet;
  644.                 node= point;
  645.                 point= 0;
  646.                 break;
  647.             }
  648.         }
  649.     }
  650. #endif
  651.     
  652.     while (pw!=NULL)
  653.     {
  654.        /* no match at all.. (yet) */
  655.         if ((pw->zone==-1 || pw->zone==zone) &&
  656.        /* zone numbers match, now net */
  657.            (pw->net==-1 || pw->net==net) &&
  658.        /* zone and net match.. node also? */
  659.            (pw->node==-1 || pw->node==node) &&
  660.        /* and how about point */
  661.            (pw->point==-1 || pw->point==point))
  662.         {
  663.                 ourzone=alias[pw->my_aka].zone;
  664.                 ournet=alias[pw->my_aka].net;
  665.                 ournode=alias[pw->my_aka].node;
  666.                 ourpoint=alias[pw->my_aka].point;
  667.                 ourpointnet=alias[pw->my_aka].pointnet;
  668.                 return 1;
  669.         }
  670.         pw=pw->next;
  671.     }
  672.     ourzone=alias[0].zone;
  673.     ournet=alias[0].net;
  674.     ournode=alias[0].node;
  675.     ourpoint=alias[0].point;
  676.     ourpointnet=alias[0].pointnet;
  677.     return 0;
  678. }
  679.  
  680. void get_passw(zone,net,node,point)
  681. int zone,net,node,point;
  682. {
  683.     struct _passw *pw;
  684.     
  685.     pw=pwd->next;
  686.     
  687.     while (pw!=NULL)
  688.     {
  689.         /* vp 27 juil 93 : no wildcards for passwords */
  690.        /* no match at all.. (yet) */
  691.         if ((/*pw->zone==-1 ||*/ pw->zone==zone) &&
  692.        /* zone numbers match, now net */
  693.            (/*pw->net==-1 ||*/ pw->net==net) &&
  694.        /* zone and net match.. node also? */
  695.            (/*pw->node==-1 ||*/ pw->node==node) &&
  696.        /* and how about point */
  697.            (/*pw->point==-1 ||*/ pw->point==point))
  698.         {
  699.                 strcpy(ourpwd,pw->passw);
  700.                 return;
  701.         }
  702.         pw=pw->next;
  703.     }
  704.     *ourpwd= '\0';
  705. }
  706.  
  707. void init(argc, argv)            /* initialize everything needed */
  708. int argc;                   /* counter */
  709. char *argv[];               /* commandline crap */
  710. {
  711.     int i,j;                /* counter */
  712.     char *p, *q;            /* nice pointers.. */
  713.     char buffer[300];       /* to store lines from AREAS.BBS etc. in */
  714.     char temp[80];          /* temp. storage */
  715.     char areasbbs[80];      /* name of file for AREAS.BBS */
  716.     int  the_box=0;         /* flags to signal call from The-Box */
  717.     FILE *fd;               /* file descriptor for control and areas.bbs */
  718. #ifndef LINN
  719.     long atol();
  720. #endif
  721.     
  722.     strcpy(areasbbs, "areas.bbs");  /* default name */
  723.  
  724.     pwd= (struct _passw *) myalloc(sizeof(struct _passw));
  725.     pwd->zone=pwd->net=pwd->node=pwd->point=0;
  726.     pwd->next=NULL;
  727.  
  728.     if (init_conf()) exit(2);       /* first parse config file */
  729.     
  730.     use_path=use_origin=use_readdress=1;
  731.     use_kludge=0;
  732.  
  733.     for (i=1;i<argc;i++)            /* parse commandline arguments */
  734.     {
  735.         if (argv[i][0]=='-')
  736.         {
  737.             switch (toupper(argv[i][1]))
  738.             {
  739.              case 'P': use_packet=1; break; /* output to packet */
  740. #ifdef LINN
  741.              case 'I': use_kludge=1; break; /* ifna kludge */
  742. #else
  743.              case 'K': use_kludge=1; break; /* ifna kludge */
  744. #endif
  745.              case 'Q': verbose=0;    break; /* quiet mode */
  746. /*             case 'S': scan_only=1;  break; /+ tiny subset */
  747.              case 'G': use_path=0;   break; /* no path line */
  748.              case 'T': ++the_box;    break; /* called with logging */
  749.              case 'O': use_origin=0; break; /* no origin line */
  750.              case 'M': maxmsgs=atoi(&argv[i][2]); break;
  751. #ifdef LINN
  752.              case 'D': add_aka = nalias; break;
  753.              case 'N': no_intl = 1;
  754. #endif
  755.              default:  message(6,"!Unknown option %s",argv[i]);
  756.             }
  757.         }
  758.         else strncpy(areasbbs,argv[i],79);
  759.     }
  760.  
  761.     mailarea=-1;                              /* don't lose msgs in area 0 */
  762.  
  763.     msgareas=0;
  764.     sprintf(buffer,"%s%s", Bpath, areasbbs);
  765.     if((fd=fopen(buffer, "r"))==NULL)
  766.     {
  767.         message(6,"-Cannot open %s, aborting...",buffer);
  768.         exit(2);
  769.     }
  770.  
  771.         /* get the MAIN origin line */
  772.     do
  773.         fgets(buffer,299,fd);
  774.     while (buffer[0]=='-' || buffer[0]==';') ;
  775.  
  776.     q=buffer+strlen(buffer)-1;
  777.     while (isspace(*q) || !*q) *q--=0;  /* get rid of trailing blanks   */
  778.     ourorigin=ctl_string(buffer);
  779.     
  780.     while (fgets(buffer,299,fd))        /* next line                    */
  781.     {
  782.         q=skip_blanks(buffer);
  783.         if (!*q || *q==';') continue;               /* comment line? */
  784.         if (strlen(q)<5) continue;
  785.         if (msgareas >= N_AREAS) {
  786.             message(6,"!Too many areas, only %d allowed\n", N_AREAS);
  787.             exit(2);
  788.         } 
  789.         if (*q=='-')
  790.         {
  791.                 switch (toupper(*(q+1)))
  792.                 {
  793.                  case 'O': q=skip_to_blank(q);
  794.                            q=skip_blanks(q);
  795.                            p= q+strlen(q)-1;
  796.                            while (isspace(*p) || !*p) *p--=0;
  797.                            AreaOrig[msgareas]=ctl_string(q);
  798.                            break;
  799.                 }
  800.                 continue;
  801.         }
  802.         for (p=temp; *q && !isspace(*q); *p++=*q++) ;
  803.         *p=0;
  804. #ifdef LINN
  805.            if (!stricmp(temp,"PASSTHRU"))
  806.             continue;
  807. #endif
  808.         AreaPath[msgareas]=ctl_string(temp);        /* copy path to area */
  809.         while (isspace(*q)) q++;
  810.         for (p=temp; *q && !isspace(*q); *p++=*q++) ;
  811.         *p=0;
  812.         AreaName[msgareas]=ctl_string(temp);        /* copy name of area */
  813.         while (*q && !isspace(*q)) q++;
  814. #ifdef LINN
  815.         if (!stricmp(AreaName[msgareas],"MAIL"))
  816. #else
  817.         if (!strnicmp(AreaName[msgareas],"MAIL",4))
  818. #endif
  819.         {                                           /* is the mail area? */
  820.             mailarea=msgareas;
  821.             free(AreaName[mailarea]);
  822.             AreaName[mailarea]=ctl_string("* Network");
  823.         }
  824.  
  825.         i=0;                            /* No destinations (yet)        */
  826.  
  827.         do
  828.         {                               /* get them all                 */
  829.             q=skip_blanks(q);
  830.             j= getaddress(q, &TZone[i], &TNet[i], &TNode[i], &TPoint[i]);
  831.             if (j==0) break;
  832.             if (j==10)
  833.             {
  834.                 message(6,"!Invalid address %s in area-file",q);
  835.                 exit(2);
  836.             }
  837.             while (*q && !isspace(*q)) q++;
  838.             i++;
  839.         }
  840.         while (*q);
  841.  
  842.         TZone[i]=TNet[i]=TNode[i]=TPoint[i]=0; /* and terminate         */
  843.         i++;
  844.  
  845.         if (i>1 && stricmp(AreaName[msgareas],"BADMSGS"))
  846.         {
  847.             ToZone[msgareas]= (int *) myalloc(sizeof(int) * i);
  848.             ToNet[msgareas]= (int *) myalloc(sizeof(int) * i);
  849.             ToNode[msgareas]= (int *) myalloc(sizeof(int) * i);
  850.             ToPoint[msgareas]= (int *) myalloc(sizeof(int) * i);
  851.             memmove(ToZone[msgareas],TZone,sizeof(int) * i);
  852.             memmove(ToNet[msgareas],TNet,sizeof(int) * i);
  853.             memmove(ToNode[msgareas],TNode,sizeof(int) * i);
  854.             memmove(ToPoint[msgareas],TPoint,sizeof(int) * i);
  855.         }
  856.  
  857. #if DEBUG
  858.   print("%s %s",AreaPath[msgareas],AreaName[msgareas]);
  859.   if (i>1 && stricmp(AreaName,"BADMSGS")) for(i=0;ToNet[msgareas][i];i++) print(" %d/%d",ToNet[msgareas][i],
  860.   ToNode[msgareas][i]);
  861.   print("\n");
  862. #endif
  863.  
  864.         if (AreaOrig[msgareas]==NULL) AreaOrig[msgareas]=ourorigin;
  865.  
  866.         ++msgareas;                     /* next area                    */
  867. #ifdef LINN
  868.     if (msgareas==N_AREAS-2) {
  869.             message(6,"!More than %d areas, areas.bbs read incomplete", N_AREAS);
  870.             break;
  871.         }
  872. #endif
  873.  
  874.     }
  875.     fclose(fd);
  876.       
  877.     if (mailarea==-1 && netpath)       /* if mailarea not defined in AREAS.BBS */
  878.     {
  879.         AreaName[msgareas]=ctl_string("* Network");
  880.         AreaPath[msgareas]=ctl_string(netpath);
  881.         mailarea=msgareas++;            /* then use the THE-BOX.CFG one */
  882.     }
  883.     
  884.     if (mailarea==-1 || !AreaPath[mailarea] || !*AreaPath[mailarea])
  885.     {
  886.         message(6,"!Don't know the path to your mailarea..");
  887.         exit(2);
  888.     }
  889.  
  890.     if ((MESSAGE=malloc(20*1024))==NULL)
  891.     {
  892.         message(6,"!Mem error");
  893.         exit(-39);
  894.     }
  895.     if (!the_box) loglevel=255;     /* called from command-line, no logging */
  896.  
  897.     sprintf(buffer,"%s.MSG",AreaPath[mailarea]);
  898.     if((MMSG=fopen(buffer, BRUP))==NULL) MMSG=fopen(buffer, BWUP);
  899.     sprintf(buffer,"%s.HDR",AreaPath[mailarea]);
  900.     if((MHDR=fopen(buffer, BRUP))==NULL) MHDR=fopen(buffer, BWUP);
  901.     if (!MMSG || !MHDR)
  902.     {
  903.         message(6,"!Error opening Mail file");
  904.         exit(1);
  905.     }
  906.     
  907.     fseek(MHDR,0l,2);               /* seek to end of mailfile          */
  908.     fseek(MMSG,0l,2);               /* to add echomail (if wanted)      */
  909. }
  910.  
  911. void Aopen()
  912. {
  913.         sprintf(oldmsg,"%s.MSG",AreaPath[area]);
  914.         if((MSG=fopen(oldmsg, BRUP))==NULL) MSG=fopen(oldmsg, BWUP);
  915.         sprintf(oldhdr,"%s.HDR",AreaPath[area]);
  916.         if((HDR=fopen(oldhdr, BRUP))==NULL) HDR=fopen(oldhdr, BWUP);
  917.         if (!MSG || !HDR)
  918.         {
  919.             message(6,"!Error opening Area file(s)");
  920.             exit(2);
  921.         }
  922. }
  923.  
  924. char *next_str (p, lookfor)
  925. char *p;
  926. char *lookfor;
  927. {
  928.    extern char *strchr();
  929.    char *found;
  930.  
  931. #if DEBUG
  932. print ("Look for '%s'\n", lookfor);
  933. #endif
  934.  
  935.     found=p;
  936.     while (1)
  937.     {
  938.         found = strchr(found, *lookfor);
  939.  
  940.       /* If we are past the end of the message, then get out */
  941.         if (found == NULL)
  942.         {
  943. #if DEBUG
  944. print("E-O-M\n");
  945. #endif
  946.             return NULL;
  947.         }
  948.  
  949. #if DEBUG
  950. print ("Match '%20.20s'\n", found);
  951. #endif
  952.  
  953.         if (strncmp (found, lookfor, strlen(lookfor)))
  954.         {
  955.             ++found;
  956.             continue;
  957.         }
  958.         else
  959.         {
  960. #if DEBUG
  961. print("match OK\n");
  962. #endif
  963.             return found;
  964.         }
  965.     }
  966. }
  967.  
  968. void GetThem(msg, str, szones, snets, snodes, spoints, tseen)
  969. char *msg;
  970. char *str;
  971. int szones[];
  972. int snets[];
  973. int snodes[];
  974. int spoints[];
  975. int *tseen;
  976. {
  977.     int j, last_net;
  978.     char *p,*q,*r;
  979.  
  980.     last_net = -1;
  981.     r=msg;
  982.  
  983.     while ((p=next_str(r,str))!=NULL)
  984.     {
  985.         q=p;
  986.        /* get begin of this line */
  987.         while (q > MESSAGE && *q!='\n') --q;
  988.         r=q;
  989.         if (*p=='\n') ++p;
  990.  
  991.         while (*p && *p!='\n')        /* not the end of the line */
  992.         {
  993.            /* found a net/node pair? */
  994.             if (isdigit(*p))
  995.             {
  996.                /* get the number. */
  997.                 getint(&p, &j);
  998.  
  999.                /* Is it a net/node pair? */
  1000.                 if (*p == ':')
  1001.                 {
  1002.                     if (getaddress(p+1, &szones[*tseen], &snets[*tseen],
  1003.                                     &snodes[*tseen], &spoints[*tseen])!=6)
  1004.                     {
  1005.                         message(6,"!Illegal address %s",p);
  1006.                         *tseen--;       /* because it's incremented below */
  1007.                     }
  1008.                     while (*p && !isspace(*p)) p++;
  1009.                     szones[*tseen]=j;
  1010.                 }
  1011.                 else
  1012.                 {
  1013.                     szones[*tseen]=ourzone;
  1014.                     spoints[*tseen]=0;
  1015.                     
  1016.                     if (*p == '/')
  1017.                     {
  1018.                         ++p;
  1019.                         last_net = snets[*tseen] = j;
  1020.                         getint(&p, &snodes[*tseen]);
  1021.                     }
  1022.                     else
  1023.                     {
  1024.                         snets[*tseen] = last_net;
  1025.                         snodes[*tseen] = j;
  1026.                     }
  1027.                     if (last_net==ourpointnet)
  1028.                     {
  1029.                         spoints[*tseen]=snodes[*tseen];
  1030.                         snets[*tseen]=ournet;
  1031.                         snodes[*tseen]=ournode;
  1032.                     }
  1033.                 }
  1034. #if DEBUG
  1035. print ("Got %d:%d/%d.%d\n", szones[*tseen],snets[*tseen],
  1036.         snodes[*tseen],spoints[*tseen]);
  1037. #endif
  1038.                 if (*tseen<440)
  1039.                 {
  1040.                     ++*tseen;
  1041.                 }
  1042.             }
  1043.             else
  1044.             {
  1045.                 ++p;
  1046.             }
  1047.         }   /* end while for this line */
  1048.         while (*p)
  1049.         {
  1050.             *q++=*p++;          /* copy rest of the message to delete line */
  1051.         }
  1052.         *q=0;
  1053.         mend=q;
  1054.     } /* end while for lines.. */
  1055. }
  1056.  
  1057. void AddOrigin()
  1058. {
  1059.         char point[9];
  1060.         char tmp[100];
  1061.         int  left;
  1062.  
  1063. #if DEBUG
  1064. print("Adding origin\n");
  1065. #endif
  1066.         if (ourpoint) sprintf(point,".%d",ourpoint);
  1067.         else *point='\0';
  1068.  
  1069.         sprint(tmp," * Origin: %%s (%d:%d/%d%s)",ourzone,ournet,ournode,point);
  1070.         left=80-(int)strlen(tmp);
  1071. #ifdef LINN
  1072.          if (((int)strlen(AreaOrig[area]))>left) AreaOrig[area][left-1]='\0';
  1073.         sprint(mend,"\n\n--- Bermuda v%s\n",UVERSION);
  1074. #else
  1075.         if (strlen(AreaOrig[area])>left) AreaOrig[area][left-1]='\0';
  1076.         sprint(mend,"\n--- Bermuda v%s\n",UVERSION);
  1077. #endif
  1078.         while (*mend) ++mend;
  1079.         sprint(mend,tmp,AreaOrig[area]);
  1080.         while (*mend) ++mend;
  1081.         *mend=0;
  1082. }
  1083.  
  1084. /* I've seen better sort algoritmes, so do you undoubtely, but this one works
  1085.    alright and for these small numbers it doesn't matter.
  1086.  */
  1087.  
  1088. void SortThem(zones,nets,nodes,points,nr,chpoints)
  1089. int zones[],nets[], nodes[], points[], *nr, chpoints;
  1090. {
  1091.     register int i, i1, left=0, right=(*nr)-1, temp=0;
  1092.     int ne1,ne2,no1,no2,p1,p2;
  1093.  
  1094. #if DEBUG
  1095. print("start sorting now....\n");
  1096. #endif
  1097.    /* sort them all (not recursive sort to prevent stack problems) */
  1098.     do
  1099.     {
  1100.         for (i=left; i<right; i++)
  1101.         {
  1102.             i1=i+1;
  1103.             if (chpoints && points[i])
  1104.             {
  1105.                 ne1=ourpointnet;
  1106.                 no1=points[i];
  1107.                 p1=0;
  1108.             }
  1109.             else
  1110.             {
  1111.                 ne1=nets[i];
  1112.                 no1=nodes[i];
  1113.                 p1=points[i];
  1114.             }
  1115.             if (chpoints && points[i1])
  1116.             {
  1117.                 ne2=ourpointnet;
  1118.                 no2=points[i1];
  1119.                 p2=0;
  1120.             }
  1121.             else
  1122.             {
  1123.                 ne2=nets[i1];
  1124.                 no2=nodes[i1];
  1125.                 p2=points[i1];
  1126.             }
  1127.             if ((zones[i] > zones[i1]) || ((zones[i] == zones[i1]) &&
  1128.                 ((ne1 > ne2) || ((ne1==ne2) && 
  1129.                 ((no1>no2) || ((no1==no2) && (p1>p2) ))))))
  1130.             {
  1131.                 temp=zones[i]; zones[i]=zones[i1]; zones[i1]=temp;
  1132.                 temp=nets[i]; nets[i]=nets[i1]; nets[i1]=temp;
  1133.                 temp=nodes[i]; nodes[i]=nodes[i1]; nodes[i1]=temp;
  1134.                 temp=points[i]; points[i]=points[i1]; points[i1]= temp;
  1135.                 temp=i;
  1136.             }
  1137.         }
  1138.         right=temp;
  1139.         for(i=right; i>left; i--)
  1140.         {
  1141.             i1=i-1;
  1142.             if (chpoints && points[i])
  1143.             {
  1144.                 ne1=ourpointnet;
  1145.                 no1=points[i];
  1146.                 p1=0;
  1147.             }
  1148.             else
  1149.             {
  1150.                 ne1=nets[i];
  1151.                 no1=nodes[i];
  1152.                 p1=points[i];
  1153.             }
  1154.             if (chpoints && points[i1])
  1155.             {
  1156.                 ne2=ourpointnet;
  1157.                 no2=points[i1];
  1158.                 p2=0;
  1159.             }
  1160.             else
  1161.             {
  1162.                 ne2=nets[i1];
  1163.                 no2=nodes[i1];
  1164.                 p2=points[i1];
  1165.             }
  1166.             if ((zones[i1] > zones[i]) || ((zones[i1] == zones[i]) &&
  1167.                 ((ne2 > ne1) || ((ne2==ne1) && 
  1168.                 ((no2>no1) || ((no2==no1) && (p2>p1) ))))))
  1169.             {
  1170.                 temp=zones[i]; zones[i]=zones[i1]; zones[i1]=temp;
  1171.                 temp=nets[i]; nets[i]=nets[i1]; nets[i1]=temp;
  1172.                 temp=nodes[i]; nodes[i]=nodes[i1]; nodes[i1]=temp;
  1173.                 temp=points[i]; points[i]=points[i1]; points[i1]= temp;
  1174.                 temp=i;
  1175.             }
  1176.         }
  1177.         left=temp;
  1178. #if DEBUG
  1179. print("Left: %d        Right: %d\n",left,right);
  1180. #endif
  1181.     }
  1182.     while (left<right);
  1183.  
  1184. #if DEBUG
  1185. print("Sorted.\n");
  1186. #endif    
  1187.  
  1188.    /* get rid of duplicates now */
  1189.     temp=*nr;
  1190.     for(i1=i=1; i<temp; i++)
  1191.     {
  1192.         if (zones[i]!=zones[i-1] || nets[i]!=nets[i-1] ||
  1193.             nodes[i]!=nodes[i-1] || points[i]!=points[i-1])
  1194.         {
  1195.             zones[i1]=zones[i];
  1196.             nets[i1]=nets[i];
  1197.             nodes[i1]=nodes[i];
  1198.             points[i1++]=points[i];
  1199.         }
  1200.     }
  1201.     if (i!=1) *nr=i1;
  1202. #if DEBUG
  1203. print("Original: %d      Now: %d\n", i,i1);
  1204. #endif
  1205. }
  1206.  
  1207. void CheckSeen()
  1208. {
  1209.     int i, fo, found, k, what;
  1210.     
  1211.     i= fo= found= 0;
  1212.  
  1213.     while (ToZone[area][i] || ToNet[area][i])
  1214.     {
  1215. #if DEBUG
  1216. print("Check for send to %d:%d/%d.%d\n",ToZone[area][i],ToNet[area][i],
  1217.         ToNode[area][i],ToPoint[area][i]);
  1218. #endif
  1219.         for (k=found; k < nSeen; k++)
  1220.         {
  1221.             if (SeenNet[k]==ToNet[area][i] && SeenNode[k]==ToNode[area][i] && 
  1222.                 SeenPoint[k]==ToPoint[area][i])
  1223.             {
  1224.                 SendTo[i]=0;
  1225.                 if (SeenZone[k]==ToZone[area][i]) found=k;
  1226.                 break;
  1227.             }
  1228.         }
  1229.         if (k==nSeen)
  1230.         {
  1231.             SendTo[i]=1;
  1232.             fo=1;
  1233.         }
  1234.         ++i;
  1235.     }
  1236.     if (!fo) return;
  1237. #if DEBUG
  1238. print("Should send message to:");
  1239. #endif
  1240.     i=-1;
  1241.     while (++i, ToNet[area][i]||ToNode[area][i])
  1242.     {
  1243.         if (!SendTo[i]) continue;
  1244. #if DEBUG
  1245. print("%d:%d/%d.%d  ",ToZone[area][i],ToNet[area][i],
  1246.         ToNode[area][i],ToPoint[area][i]);
  1247. #endif
  1248.         SeenZone[nSeen]=ToZone[area][i];
  1249.         SeenNet[nSeen]=ToNet[area][i];
  1250.         SeenNode[nSeen]=ToNode[area][i];
  1251.         SeenPoint[nSeen++]=ToPoint[area][i];
  1252.     }
  1253. #if DEBUG
  1254. print("\nSort now..");
  1255. #endif
  1256.     SortThem(SeenZone,SeenNet,SeenNode,SeenPoint,&nSeen,1);
  1257.  
  1258. #if DEBUG
  1259. print("\nCreating message to ");
  1260. #endif
  1261.     i=-1;
  1262.     while (++i, ToNet[area][i]||ToNode[area][i])
  1263.     {
  1264.         if (!SendTo[i]) continue;
  1265. #if DEBUG
  1266. print("%d:%d/%d.%d ",ToZone[area][i],ToNet[area][i],
  1267.         ToNode[area][i],ToPoint[area][i]);
  1268. #endif
  1269.         what= ((ToPoint[area][i]) ? POINTS : 0) |
  1270.                (use_tiny ? LOCALS:OTHERS);
  1271.         writemessage(use_packet ? SCANFILE : OUTBOUND,what,
  1272.              ToZone[area][i],ToNet[area][i],ToNode[area][i],ToPoint[area][i]);
  1273.     }
  1274. #if DEBUG
  1275. print("\n");
  1276. #endif    
  1277. }
  1278.  
  1279. void PurgeBlanks()           /* delete trailing blanks */
  1280. {
  1281.     char *p;
  1282.     
  1283.    /* point p at end of message */
  1284.     p=mend;
  1285.    /* if it's the trailing '\0' then skip it. */
  1286.     if (p>MESSAGE && *p==0) --p;
  1287.    /* back till begin of message or any non blank */
  1288.     while (p>MESSAGE && isspace(*p)) --p;
  1289.    /* p points to valid char now (non blank) so increment by one */
  1290.     *(++p)='\0';
  1291.     mend=p;
  1292. }
  1293.  
  1294. /* keep in memory the name of the posters */
  1295. struct Scanned {
  1296.     char from[36];
  1297.     struct Scanned *next;
  1298. } *scan_start=NULL, *scan_cur, *scan_tmp;
  1299.  
  1300. void CheckEcho()
  1301. {
  1302.     int i;
  1303.     
  1304.    /* first check if msg valid for sending. */
  1305.     if (hdr.flags & SENT ||
  1306.         hdr.flags & FILEATCH) return;
  1307.     if (next_str(MESSAGE,"\nNOECHO") || next_str(MESSAGE,"\nnoecho")) return;
  1308.   
  1309.    /* Get the seen-bys (deletes the lines..) */
  1310.     nSeen=0;
  1311.     GetThem(MESSAGE, "\n\01SEEN-BY:", SeenZone, SeenNet, SeenNode,
  1312.             SeenPoint, &nSeen);
  1313.     GetThem(MESSAGE, "\nSEEN-BY:", SeenZone, SeenNet, SeenNode,
  1314.             SeenPoint, &nSeen);
  1315.  
  1316.     SeenZone[nSeen]=ourzone;
  1317.     SeenNet[nSeen]=ournet;
  1318.     SeenNode[nSeen]=ournode;
  1319.     SeenPoint[nSeen++]=ourpoint;
  1320.  
  1321.    /* add our own numbers (AKAs etc.) */
  1322.     for (i=0;i<add_aka && i<nalias;i++)
  1323.     {
  1324. #ifdef LINN
  1325.         if (alias[i].zone==ourzone) {
  1326. #endif
  1327.            SeenZone[nSeen]=alias[i].zone;
  1328.            SeenNet[nSeen]=alias[i].net;
  1329.            SeenNode[nSeen]=alias[i].node;
  1330.            SeenPoint[nSeen++]=alias[i].point;
  1331. #ifdef LINN
  1332.     }
  1333. #endif
  1334.     }
  1335.  
  1336.    /* get them in the correct order again.. */
  1337.     SortThem(SeenZone,SeenNet,SeenNode,SeenPoint, &nSeen,0);
  1338.  
  1339. #if DEBUG
  1340. print("Message SEEN-BY:");
  1341. for (i=0;i<nSeen;i++) print(" %d:%d/%d.%d",SeenZone[i],SeenNet[i],
  1342.      SeenNode[i],SeenPoint[i]);
  1343. print("\n");
  1344. #endif
  1345.     
  1346.    /* get the path, not restored if not in use (get rid of line anyway..) */
  1347.     nPath=0;
  1348.     GetThem(MESSAGE, "\n\01PATH:", PathZone, PathNet, PathNode,
  1349.             PathPoint, &nPath);
  1350. #if DEBUG
  1351. print("Message PATH:");
  1352. for (i=0;i<nPath;i++) print(" %d:%d/%d.%d",PathZone[i],PathNet[i],
  1353.         PathNode[i],PathPoint[i]);
  1354. print("\n");
  1355. #endif
  1356.     
  1357.    /* Get rid of all trailing blanks now. */
  1358.     PurgeBlanks();
  1359.  
  1360.    /* Check if we've got an origin-line already (and add if not and we use one) */
  1361.     if (use_origin)
  1362.     {
  1363.         if (next_str(MESSAGE,"\n * Origin:")==NULL) AddOrigin();
  1364.     }
  1365.     endbody=mend;   /* message body ends HERE */
  1366.     
  1367.    /* Now check for nodes to send the message to (and send those msgs) */
  1368.     CheckSeen();
  1369.     
  1370.    /* Flag message as scanned */
  1371.     hdr.mailer[7] |= MSGSCANNED;
  1372. #ifdef LINN
  1373.     /* for compatibility with other scanners */
  1374.     hdr.flags |= SENT;
  1375.     
  1376.     if (scan_start) {
  1377.         scan_cur->next=malloc (sizeof(struct Scanned));
  1378.         scan_cur=scan_cur->next;
  1379.     } else {
  1380.         scan_start=malloc (sizeof(struct Scanned));
  1381.         scan_cur=scan_start;
  1382.     }
  1383.     scan_cur->next=NULL;
  1384.     strcpy (scan_cur->from, hdr.from);
  1385. #endif
  1386. }
  1387.  
  1388. readmessage()
  1389. {
  1390.     *MESSAGE=0;
  1391.     if (fread((char *) &hdr, sizeof(struct Hdr), 1, HDR)!=1) return ENDOFAREA;
  1392.     
  1393.     if (hdr.flags & DELETED) return SKIP;
  1394.     if ((hdr.flags & KILLSEND) && (hdr.flags & SENT)) return SKIP;
  1395.     if (hdr.mailer[7] & MSGSCANNED) return SKIP;
  1396.     
  1397.     fseek(MSG,hdr.Mstart,0);
  1398.     if (fread(MESSAGE, hdr.size, 1, MSG)!=1)
  1399.     {
  1400.         message(6,"!Error reading message from file");
  1401.         return SKIP;
  1402.     }
  1403.     endbody=mend= MESSAGE + (hdr.size-1);
  1404.     return MSGALRIGHT;
  1405. }
  1406.  
  1407. void add(p) char *p;
  1408. {       while (*p)
  1409.         {       *mend++=*p++;
  1410.                 x++;
  1411.         }
  1412. }
  1413.  
  1414. void AddThem(addstr,zones,nets,nodes,points,nr,dopoints,dozones)
  1415. char *addstr;
  1416. int zones[], nets[], nodes[], points[], nr, dopoints, dozones;
  1417. {
  1418.     int lastnet, i, len, tnet, tnode;
  1419.     char str[20];
  1420.     
  1421.     x=100;
  1422.     lastnet=-1;
  1423.     for(i=0; i<nr; i++)
  1424.     {
  1425.         if (zones[i]!=ourzone)
  1426.         {
  1427.             if (dozones)
  1428.             {
  1429.                 tnet=-1;
  1430.                 sprintf(str," %d:%d/%d.%d",zones[i],nets[i],nodes[i],points[i]);
  1431.             }
  1432.             else *str=0;
  1433.         }
  1434.         else
  1435.         {
  1436. #if DEBUG
  1437. print("%d/%d.%d -> ",nets[i],nodes[i],points[i]);
  1438. #endif
  1439.             if (points[i])
  1440.             {
  1441.                 tnet=ourpointnet;
  1442.                 tnode=points[i];
  1443.             }
  1444.             else
  1445.             {
  1446.                 tnet=nets[i];
  1447.                 tnode=nodes[i];
  1448.             }
  1449.             
  1450.             if (!dopoints && points[i] && !(points[i]==ourpoint &&
  1451.                 nodes[i]==ournode && nets[i]==ournet)) continue;
  1452.  
  1453.             if (lastnet==tnet) sprintf(str," %d",tnode);
  1454.             len=(int)strlen(str);
  1455.             if (lastnet!=tnet || (len+x > 76))
  1456.                 sprintf(str," %d/%d",tnet,tnode);
  1457.         }
  1458.         len=(int)strlen(str);
  1459.         if (len+x >76)
  1460.         {
  1461.             x=0;
  1462.             add(addstr);
  1463.         }
  1464. #if DEBUG
  1465. print("%s\n",str);
  1466. #endif
  1467.         add(str);
  1468.         lastnet=tnet;
  1469.     }
  1470.     *mend=0;
  1471. }
  1472.  
  1473. void AddSeen(what)
  1474. int what;
  1475. {
  1476.     char sline[20];
  1477.     int i;
  1478.  
  1479.     sprintf(sline, "\n%sSEEN-BY:", use_kludge ? "\01" : "");
  1480.     if (what&LOCALS)
  1481.     {
  1482.         for (i=0; ToNet[area][i]|ToNode[area][i]; ++i);
  1483.         AddThem(sline,*ToZone,*ToNet,*ToNode,*ToPoint,i,    /* added '*', VP */
  1484.                (what&POINTS),(what&DIFFZONE));
  1485.     }
  1486.     else AddThem(sline,SeenZone,SeenNet,SeenNode,SeenPoint,
  1487.                   nSeen, (what&POINTS), (what&DIFFZONE));
  1488. }
  1489.  
  1490. void AddPath(add)
  1491. int add;
  1492. {
  1493.     int th=1;
  1494.     
  1495.     if (PathZone[nPath-1]==ourzone && PathNet[nPath-1]==ournet && 
  1496.         PathNode[nPath-1]==ournode && PathPoint[nPath-1]==ourpoint) --th;
  1497.     PathZone[nPath]=ourzone;
  1498.     PathNet[nPath]=ournet;
  1499.     PathNode[nPath]=ournode;
  1500.     PathPoint[nPath]=ourpoint;
  1501.  
  1502.     AddThem("\n\01PATH:",PathZone,PathNet,PathNode,PathPoint,nPath+th,-1,0);
  1503. }
  1504.  
  1505. void OpenPacket(zone,net,node,point)
  1506. int zone, net, node, point;
  1507. {
  1508.     struct time t;
  1509.     struct date d;
  1510.     struct _pkthdr phdr;
  1511.     char fname[80];
  1512.     int  i;
  1513.  
  1514. #if DEBUG
  1515. print("Open packet %d:%d/%d.%d\n",zone,net,node,point);
  1516. #endif
  1517.     /* Get password first before all information is destroyed */
  1518.     get_passw(zone,net,node,point);
  1519. #ifdef LINN /* as in pack */
  1520.     getalias(zone,net,node,point);
  1521. #endif
  1522.  
  1523.     /* save the 4-D address first */
  1524.     pktzone= zone;
  1525.     pktnet= net;
  1526.     pktnode= node;
  1527.     pktpoint= point;
  1528.  
  1529.     if (point)
  1530.     {
  1531.         for (i=0; i<nalias; i++)
  1532.         {
  1533.             if (alias[i].zone==zone && alias[i].net==net &&
  1534.                 alias[i].node==node && alias[i].point==0)
  1535.             {
  1536.                 net= alias[i].pointnet;
  1537.                 node= point;
  1538.                 point= 0;
  1539.                 pktfake = net;
  1540.                 break;
  1541.             }
  1542.         }
  1543.         if (point)
  1544.         {
  1545.             message(6,"!Can't scan for points of other BBSes!");
  1546.             exit(2);
  1547.         }
  1548.     } else {
  1549.         pktfake = 0;
  1550.     }
  1551.  
  1552.     /* try to open existing files, first .WM then .NM */
  1553.  
  1554. #ifdef LINN
  1555.     /* how boring ... */
  1556.     if (binkley) {
  1557.        if (zone==alias[0].zone) {
  1558.          sprint(fname, "%s%03z%03z00.HPT", hold, net, node);
  1559.          pktfile=fopen(fname, BRUP);
  1560.          if (pktfile == NULL) {
  1561.         sprint(fname, "%s%03z%03z00.OPT", hold, net, node);
  1562.             pktfile=fopen(fname,BRUP);
  1563.          }
  1564.        } else {
  1565.          sprint(fname, "%s.%03y%c%03z%03z00.HPT", holdbink, zone, DIRSEP, net, node);
  1566.          pktfile=fopen(fname, BRUP);
  1567.          if (pktfile == NULL) {
  1568.         sprint(fname, "%s.%03y%c%03z%03z00.OPT", holdbink, zone, DIRSEP, net, node);
  1569.             pktfile = fopen(fname,BRUP);
  1570.          }
  1571.        }
  1572.     } else {
  1573.        sprint(fname, "%s%02z%03z%03z.WM", hold, zone, net, node);
  1574.        pktfile = fopen(fname,BRUP);
  1575.        if (pktfile == NULL) {
  1576.         sprint(fname, "%s%02z%03z%03z.NM", hold, zone, net, node);
  1577.             pktfile = fopen(fname,BRUP);
  1578.        }
  1579.     }
  1580. #else
  1581.     sprint(fname, "%s%02z%03z%03z.WM", hold, zone, net, node);
  1582.     pktfile = fopen(fname,BRUP);
  1583.     if (pktfile == NULL) {
  1584.         sprint(fname, "%s%02z%03z%03z.NM", hold, zone, net, node);
  1585.         pktfile = fopen(fname,BRUP);
  1586.     }
  1587. #endif
  1588.  
  1589.     if (pktfile!=NULL)
  1590.     {
  1591.         fseek(pktfile,-2L,2);
  1592.         return;
  1593.     }
  1594.  
  1595.     pktfile= fopen(fname,BWUP);
  1596.     if (pktfile==NULL)
  1597.     {
  1598.         message(6,"!Can't open file %s",fname);
  1599.         exit(1);
  1600.     }
  1601.  
  1602.     /* new packet, we've to make a header first */
  1603.     getdate(&d);
  1604.     gettime(&t);
  1605.     memset(&phdr, 0, sizeof(struct _pkthdr));
  1606.  
  1607.     /* are we a point and not to boss then re-address */
  1608.     if (ourpoint)
  1609.     {
  1610.         if (ournode!=node || ournet!=net || ourzone!=zone)
  1611.         {
  1612.             phdr.ph_onode= inteli(-1);
  1613.             phdr.ph_onet = inteli(ournet);
  1614.         }
  1615.         else
  1616.         {
  1617.             phdr.ph_onode= inteli(ourpoint);
  1618.             phdr.ph_onet= inteli(ourpointnet);
  1619.         }
  1620.     }
  1621.     else
  1622.     {
  1623.         phdr.ph_onode=inteli(ournode);
  1624.         phdr.ph_onet=inteli(ournet);
  1625.     }
  1626.     phdr.ph_ozone=inteli(ourzone);
  1627.     phdr.ph_dnode=inteli(node);
  1628.     phdr.ph_dnet=inteli(net);
  1629.     phdr.ph_dzone=inteli(zone);
  1630.     phdr.ph_yr=inteli(d.da_year);
  1631.     phdr.ph_mo=inteli(d.da_mon-1);
  1632.     phdr.ph_dy=inteli(d.da_day-1);
  1633.     phdr.ph_hr=inteli(t.ti_hour);
  1634.     phdr.ph_mn=inteli(t.ti_min);
  1635.     phdr.ph_sc=inteli(t.ti_sec);
  1636.     phdr.ph_rate=0;
  1637.     phdr.ph_ver=inteli(2);
  1638.     phdr.ph_prod=inteli(isBERMUDA);
  1639.     strncpy(phdr.ph_pwd,ourpwd,8);
  1640.     if( fwrite((char *)&phdr, sizeof(struct _pkthdr), 1, pktfile) !=1)
  1641.     {
  1642.         message(6,"-Write error (disk full??)");
  1643.         exit(1);
  1644.     }
  1645. }
  1646.  
  1647. void ClosePacket()
  1648. {
  1649. #if DEBUG
  1650. print("Close packet\n");
  1651. #endif
  1652.     if (pktfile)
  1653.     {
  1654.         pktzone= pktnet= pktnode= pktpoint= 0;
  1655.         if (fwrite("\0\0", 2, 1, pktfile)!=1)
  1656.         {
  1657.             message(6,"!Error writing to package");
  1658.             exit(1);
  1659.         }
  1660.         fclose(pktfile);
  1661.     }
  1662. }
  1663.  
  1664. void MakeHdr(Mhdr)
  1665. struct Hdr *Mhdr;
  1666. {
  1667.     struct _pktmsgs mh;
  1668.     
  1669. #if DEBUG
  1670. print("MakeHdr\n");
  1671. #endif
  1672.     mh.pm_ver=inteli(2);
  1673.     mh.pm_onode=inteli(Mhdr->Onode);
  1674.     mh.pm_onet=inteli(Mhdr->Onet);
  1675.     mh.pm_dnode=inteli(Mhdr->Dnode);
  1676.     mh.pm_dnet=inteli(Mhdr->Dnet);
  1677.     mh.pm_attr=inteli(Mhdr->flags&0x3413);
  1678.     mh.pm_cost=inteli(Mhdr->cost);
  1679.     fwrite((char *)&mh, sizeof(struct _pktmsgs), 1, pktfile);
  1680.     fprintf(pktfile,"%19s",Mhdr->time);
  1681.     putc('\0',pktfile);
  1682.     fprintf(pktfile,"%s",Mhdr->to);        /* from & to */
  1683.     putc('\0',pktfile);
  1684.     fprintf(pktfile,"%s",Mhdr->from);
  1685.     putc('\0',pktfile);
  1686.     fprintf(pktfile,"%s",Mhdr->topic);     /* topic */
  1687.     putc('\0',pktfile);
  1688.  
  1689. #ifdef LINN
  1690.     if (no_intl)
  1691. #endif
  1692.     if (Mhdr->Ozone && Mhdr->Dzone && (Mhdr->Ozone!=Mhdr->Dzone))
  1693.         fprintf(pktfile,"\01INTL %d:%d/%d %d:%d/%d\r\n", Mhdr->Dzone,
  1694.           Mhdr->Dnet, Mhdr->Dnode, Mhdr->Ozone, Mhdr->Onet, Mhdr->Onode);
  1695. }
  1696.  
  1697. void PktWrite(str, len)
  1698. char *str;
  1699. int len;
  1700. {
  1701. #if DEBUG
  1702. print("PktWrite\n");
  1703. #endif
  1704.     while (len--)
  1705.     {
  1706.         if (*str=='\n') putc('\r',pktfile);
  1707.         else putc(*str,pktfile);
  1708.         str++;
  1709.     }
  1710.     if (ferror(pktfile))
  1711.     {
  1712.         message(6,"!Error writing to packet-file");
  1713.         exit(1);
  1714.     }
  1715. }
  1716.  
  1717. void writehdr()
  1718. {
  1719.     fflush(HDR);
  1720.     fseek(HDR, ftell(HDR) - sizeof(struct Hdr), 0);
  1721.     if (fwrite((char *) &hdr, sizeof(struct Hdr), 1, HDR)!=1)
  1722.     {
  1723.         message(6,"!Fatal error writing to %s",oldhdr);
  1724.         exit(1);
  1725.     }
  1726.     fflush(HDR);
  1727.     fseek(HDR,ftell(HDR),0);
  1728. }
  1729.  
  1730. void writemessage(where,what,zone,net,node,point)
  1731. int where;
  1732. int what;
  1733. int zone,net,node,point;
  1734. {
  1735.     int i;
  1736.     char sline[20];
  1737.  
  1738. #ifdef LINN
  1739.     getalias (zone, net, node, point);
  1740. #endif
  1741.     mend=endbody;
  1742.     if (what)
  1743.     {
  1744.         if (zone!=ourzone) 
  1745.         {
  1746.             int z[3],ne[3],no[3],p[3],i;
  1747.             
  1748.             i=2;
  1749.             z[0]=ourzone; z[1]=ourzone;
  1750.             ne[0]=ournet; ne[1]=net;
  1751.             no[0]=ournode; no[1]=node;
  1752.             p[0]=ourpoint; p[1]=0;
  1753.             SortThem(z,ne,no,p,&i,1);
  1754.             sprintf(sline, "\n%sSEEN-BY:", use_kludge ? "\01" : "");
  1755.             AddThem(sline,z,ne,no,p,2,1,1);
  1756.         }
  1757.         else AddSeen(what);
  1758.         if (use_path) AddPath(zone!=ourzone);
  1759.  
  1760.         if (use_readdress)
  1761.         {
  1762.             hdr.Ozone = ourzone;
  1763.             hdr.Onet  = ournet;
  1764.             hdr.Onode = ournode;
  1765.             hdr.Opoint= ourpoint;
  1766.             if (ourpoint)
  1767.             {
  1768.                 hdr.Onet= ourpointnet;
  1769.                 hdr.Onode= ourpoint;
  1770.                 hdr.Opoint=0;
  1771.             }
  1772.         }
  1773.     }
  1774.     switch (where)
  1775.     {
  1776.       case OUTBOUND: memmove((char *) &Mhdr, (char *) &hdr, sizeof(struct Hdr));
  1777.                     Mhdr.Mstart= ftell(MMSG);
  1778.                     if (what)
  1779.                     {
  1780.                         ++echomsgs;
  1781.                         if (fwrite(ThisArea, strlen(ThisArea),1, MMSG)!=1)
  1782.                         {
  1783.                             message(6,"!Fatal error writing to mail");
  1784.                             exit(1);
  1785.                         }
  1786.                         Mhdr.size=(int)strlen(ThisArea);
  1787.                     }
  1788.                     else Mhdr.size=0;
  1789.                     *mend++='\n';
  1790.                     *mend='\0';
  1791.                     Mhdr.size += (int)(mend-MESSAGE)+2;
  1792.                     Mhdr.Dzone = zone;
  1793.                     Mhdr.Dnet  = net;
  1794.                     Mhdr.Dnode = node;
  1795.                     Mhdr.Dpoint= point;
  1796.                     Mhdr.flags |= (MSGLOCAL|KILLSEND);
  1797.                     Mhdr.parent = 0;
  1798.                     for (i=0; i<8; i++) Mhdr.mailer[i]=0;
  1799.                     Mhdr.cost=0;
  1800.                     if (fwrite((char *) &Mhdr, sizeof(struct Hdr), 1, MHDR)!=1)
  1801.                     {
  1802.                         message(6,"!Fatal error writing to mail");
  1803.                         exit(1);
  1804.                     }
  1805.                     if (fwrite(MESSAGE, ((mend-MESSAGE)+2), 1, MMSG)!=1)
  1806.                     {
  1807.                         message(6,"!Fatal error writing to mail");
  1808.                         exit(1);
  1809.                     }
  1810.                     break;
  1811.       case SCANFILE: memmove((char *) &Mhdr, (char *) &hdr, sizeof(struct Hdr));
  1812.                     if (zone!=pktzone || net!=pktnet || node !=pktnode ||
  1813.                         point!=pktpoint)
  1814.                     {
  1815.                         ClosePacket();
  1816.                         OpenPacket(zone,net,node,point);
  1817.                     }
  1818.                     *mend++='\n';
  1819.                     *mend='\0';
  1820.                     if (point) {
  1821.                         net = pktfake;
  1822.                         node = pktpoint;
  1823.                         point = 0;
  1824.                     }
  1825.                     Mhdr.Dzone = zone;
  1826.                     Mhdr.Dnet  = net;
  1827.                     Mhdr.Dnode = node;
  1828.                     Mhdr.Dpoint= point;
  1829.                     Mhdr.flags |= (MSGLOCAL);
  1830.                     Mhdr.cost=0;
  1831.                     MakeHdr(&Mhdr);
  1832.                     if (what)
  1833.                     {
  1834.                         ++echomsgs;
  1835.                         PktWrite(ThisArea, (int)strlen(ThisArea));
  1836.                     }
  1837.                     PktWrite(MESSAGE, ((int)(mend-MESSAGE)+1));
  1838.                     break;
  1839.       default:      message(6,"?Don't know how to handle %02x in messagewrite",where);
  1840.     }
  1841. }
  1842.  
  1843. void cleanEcho()
  1844. {       int current,i;
  1845.         int msgok;
  1846.  
  1847.         current=0;
  1848.  
  1849.         sprint(ThisArea, "%sAREA:%s\n", (use_kludge?"\01":""), AreaName[area]);
  1850.  
  1851. #if DEBUG
  1852. if (echoarea) print("AreaID: %s\n",ThisArea);
  1853. #endif
  1854.  
  1855.         getalias(ToZone[area][0],ToNet[area][0],ToNode[area][0],
  1856.                         ToPoint[area][0]);
  1857.         i=0;
  1858.         while (ToZone[area][i]||ToNet[area][i]||ToNode[area][i])
  1859.         {
  1860.             ++i;
  1861.         }
  1862.         SortThem(ToZone[area],ToNet[area],ToNode[area],ToPoint[area],&i,0);
  1863.  
  1864.         i = echomsgs;
  1865.  
  1866.         while (msgok=readmessage(), msgok!=ENDOFAREA)
  1867.         {
  1868.                 if (msgok!=SKIP)
  1869.                 {
  1870.                         if (echomsgs<maxmsgs)
  1871.                         {
  1872.                                 CheckEcho();
  1873.  
  1874.                                 /* signal this one has been scanned */
  1875.                                 writehdr();
  1876.                         }
  1877.                 }
  1878.                 current++;
  1879.         }
  1880.         if (verbose) print("%d message(s), %d new\n",current,echomsgs-i);
  1881. }
  1882.  
  1883. void Aclose()
  1884. {
  1885.         fclose(HDR);
  1886.         fclose(MSG);
  1887. }
  1888.  
  1889. void LogScanned()
  1890. {
  1891.     scan_cur=scan_start;
  1892.     while (scan_cur) {
  1893.         message(3,"*Scanned a message from %s to %s", scan_cur->from, AreaName[area]);
  1894.         scan_tmp=scan_cur;
  1895.         scan_cur=scan_cur->next;
  1896.         free(scan_tmp);
  1897.     }
  1898.     scan_start=NULL;
  1899. }
  1900.  
  1901. void deinitialize()
  1902. {
  1903.         if (pktzone!=0 || pktnet!=0 || pktnode!=0 ||
  1904.             pktpoint!=0) ClosePacket();
  1905.         if (verbose)
  1906.         {
  1907.                 print("\n");
  1908.                 message(1,"+%d echomail message(s) created\n\n",echomsgs);
  1909.         }
  1910. }
  1911.  
  1912. main(argc, argv)
  1913. int argc;
  1914. char *argv[];
  1915. {
  1916.     fprintf(stderr,
  1917.      "BERMUDA : FidoNet compatible message processing software\n");
  1918.     fprintf(stderr,
  1919.      "SCAN utility ; Version %s created %s at %s\n\n",UVERSION,
  1920.      __DATE__,__TIME__);
  1921.     fflush(stderr);
  1922.  
  1923.     init(argc, argv);
  1924.     for (area=0;area<msgareas;area++)
  1925.     {
  1926.         if (area!=mailarea && ToZone[area] != NULL)
  1927.         {
  1928.             if (verbose)
  1929.                 print("Processing ECHO area %25.25s : ",AreaPath[area]);
  1930.  
  1931.             Aopen();        /* open the current area    */
  1932.             cleanEcho();    /* delete and scan messages */
  1933.             Aclose();       /* close the current area   */
  1934.             LogScanned();
  1935.         }
  1936.     }
  1937.     deinitialize();
  1938.     return 0;
  1939. }
  1940.  
  1941.