home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / XGRP_000.SZH / EMAILIN.C < prev    next >
C/C++ Source or Header  |  1991-08-22  |  62KB  |  1,808 lines

  1. /* net/echo/groupmail tosser/forwarder */
  2.  
  3. /* NOTE:  this code maintains but *does not use* SEEN-BYs.  This code
  4.    *eliminates* current ^aPATH lines and replaces/merges them with
  5.    ^aNPTH lines (5-D).  Tiny Seenbys are the default; use them wherever
  6.    possible and cut down on useless overhead.  Fingers down the throat
  7.    of echopol.  Long live TJ and other anarchistic SOBs like himself. */
  8.  
  9. #include <limits.h>
  10. #include "xgroup.h"
  11.  
  12. #define MAXKLUDGE   256
  13. #define MAXARCEXTS    7
  14. #define IS_UNKNOWN    1
  15. #define IS_INSECURE   2
  16. #define IS_ADUPE      3
  17. #define IS_NOFORWARD  4
  18.  
  19. /* local-only functions */
  20.  
  21. static int    _fastcall bitch_and_moan_again (ADDR *addr,char *area);
  22. static int    _fastcall bitch_and_moan (ADDR *addr,char *area);
  23. static int  _fastcall crack_pkt (char *pktname);
  24. static int  _fastcall import (char *buff,XMSG *msg,ECHOREC *currecho,
  25.                               GROUP *currgroup,word msgnum);
  26. static int  _fastcall get_msg (word buflen,char *buff,char **text,int fp,
  27.                                XMSG *msg);
  28. static void _fastcall report (void);
  29. static int  _fastcall open_msg_files (word areano);
  30. static int  _fastcall forward (char *buff,XMSG *xmsg,ECHOREC *currecho,
  31.                                GROUP *currgroup,ADDR *pktaddr);
  32. static int  _fastcall unknown (char *buff,XMSG *xmsg,char *area);
  33. static int  _fastcall insecure (char *buff,XMSG *xmsg,char *area);
  34. static int  _fastcall isadupe (char *buff,XMSG *xmsg,char *area);
  35. static int  _fastcall is_notforwarded (char *buff,XMSG *xmsg);
  36. static int  _fastcall open_pkt (ADDR *addr,ADDR *faddr,int which);
  37. static word _fastcall find_last_scanned (int dataptr);
  38. static int  _fastcall write_pkt_msg (int fp,XMSG *amsg,SB *opth,ADDR *naddr,
  39.                                      ADDR *maddr,char *text,char *area,
  40.                                      SB *sb);
  41.  
  42. word _fastcall make_message (char *text,XMSG *xmsg);
  43.  
  44. /* local-only vars */
  45.  
  46. static int    dataptr = -1,textptr = -1,grunged_date = 0, grunged_area = 0,
  47.             grunged_seenbys = 0;
  48. static word netimported = 0,netforwarded = 0,unknownmsgs = 0,
  49.             insecuremsgs = 0,numdupes = 0,notforwarded = 0,numassholes = 0;
  50. static char *newpath,*pathline,*seenby,*area,*kludge,*origin,
  51.             to_domain[39],from_domain[39];
  52. static long msgidcrc,serialno,numpassthru = 0L,numechoforwarded = 0L;
  53.  
  54. /* external var references */
  55.  
  56. extern char     buffer[1024];
  57. extern GROUP    *group;
  58. extern CONTROLS control;
  59. extern ADDR     *myaddr;
  60. extern ECHOREC  *echos;
  61. extern ASSHOLE  *assholes;
  62. extern TONAMES  *tonames;
  63. extern char     *groupin;
  64. extern char     *groupout;
  65. extern char     *grouphold;
  66. extern char     *msgdir;
  67. extern char     *outbound;
  68. extern char     *inbound;
  69. extern char     *archive;
  70. extern char     *unarchive;
  71. extern word     packsize;
  72. extern word     netarea;
  73. extern DUPES    *dupes;
  74. extern word     nextdupe,maxdupes;
  75. extern char     founddupes;
  76. extern char     *putmsgs;
  77.  
  78.  
  79.  
  80.  
  81. void _fastcall echo_import_mail (void) {
  82.  
  83.     FILEFINDBUF f;
  84.     int         search_handle,num_matches,x = 0;
  85.     static char arcext[MAXARCEXTS][3] = {
  86.         "MO","TU","WE","TH","FR","SA","SU"};
  87.     char        arcfile[257] = "",*p;
  88.     GROUP       *currgroup;
  89.     long        diskspace;
  90.     struct __sizeinfo__ {
  91.         long id;
  92.         long sectors;
  93.         long alloc;
  94.         long avail;
  95.         word bytes;
  96.     }           sz;
  97.  
  98.  
  99.     /* move groupmail files to groupin dir */
  100.  
  101.     printf("\nSearching for and moving group files...");
  102.  
  103.     search_handle = 1;
  104.     num_matches = 1;
  105.     sprintf(buffer,"%s/*.*",inbound);
  106.     if(!DosFindFirst(buffer,&search_handle,0,&f,
  107.       sizeof(FILEFINDBUF),&num_matches,0L)) {
  108.         do {
  109.             p = strrchr(f.achName,'.'); /* verify it's a group file */
  110.             if(!p) {
  111.                 goto ContHere;    /* can't be a group file */
  112.             }
  113.             *p = 0;
  114.             currgroup = group;
  115.             while(currgroup) {
  116.                 if(!stricmp(f.achName,currgroup->id)) break;
  117.                 currgroup = currgroup->next;
  118.             }
  119.             *p = '.';
  120.             if(!currgroup) {
  121.                 goto ContHere;   /* not a group file */
  122.             }
  123.             p++;
  124.             if(ext_reserved(p)) { /* check various reserved extensions */
  125.                 goto ContHere;   /* not a group file */
  126.             }
  127.  
  128.             /* is a group file; move it */
  129.  
  130.             if(toupper(*groupin) == toupper(*inbound)) {
  131.                 sprintf(buffer,"%s/%s %s/%s",inbound,f.achName,groupin,f.achName);
  132.                 p = strchr(buffer,' ');
  133.                 *p = 0;
  134.                 p++;
  135.                 DosMove(buffer,p,0L);
  136.             }
  137.             else {
  138.                 sprintf(buffer,"COPY %s/%s %s/%s > NUL",inbound,f.achName,groupin,f.achName);
  139.                 system(buffer);
  140.                 sprintf(buffer,"%s/%s",inbound,f.achName);
  141.                 my_unlink(buffer);
  142.             }
  143.  
  144. ContHere:
  145.  
  146.             num_matches = 1;
  147.         } while(!DosFindNext(search_handle,&f,sizeof(FILEFINDBUF),
  148.                              &num_matches));
  149.         DosFindClose(search_handle);
  150.     }
  151.  
  152.     printf("\nImporting net/echomail -- forwarding groupmail...");
  153.  
  154.     search_handle = 1;
  155.     num_matches = 1;
  156.     sprintf(buffer,"%s/*.?UT",inbound);
  157.     if(!DosFindFirst(buffer,&search_handle,0,&f,
  158.       sizeof(FILEFINDBUF),&num_matches,0L)) {
  159.         do {
  160.             sprintf(buffer,"%s/%s",inbound,f.achName);
  161.             if(!access(buffer,6)) {
  162.                 crack_pkt(buffer);
  163.             }
  164.             else {
  165.                 printf("\nSkipped %s--no read/write access",f.achName);
  166.                 logf("Skipped %s--no read/write access",f.achName);
  167.             }
  168.             num_matches = 1;
  169.         } while(!DosFindNext(search_handle,&f,sizeof(FILEFINDBUF),
  170.                              &num_matches));
  171.         DosFindClose(search_handle);
  172.     }
  173.  
  174. DoPackets:
  175.  
  176.     search_handle = 1;
  177.     num_matches = 1;
  178.     sprintf(buffer,"%s/*.PKT",inbound);
  179.     if(!DosFindFirst(buffer,&search_handle,0,&f,
  180.       sizeof(FILEFINDBUF),&num_matches,0L)) {
  181.         do {
  182.             DosQFSInfo(0,1,&sz,sizeof(sz));
  183.             diskspace = sz.avail * sz.sectors * sz.bytes;
  184.             if(diskspace < f.cbFile * 2L) {
  185.                 printf("\nProbably insufficient diskspace to process \"%s\"",f.achName);
  186.                 printf("\nFilesize: %ld  Diskspace: %ld",f.cbFile,diskspace);
  187.                 logf("Probably insufficient diskspace to process \"%s\"",f.achName);
  188.                 logf("Filesize: %ld  Diskspace: %ld",f.cbFile,diskspace);
  189.                 goto SkipPkt;
  190.             }
  191.  
  192.             sprintf(buffer,"%s/%s",inbound,f.achName);
  193.             if(!access(buffer,6)) {
  194.                 crack_pkt(buffer);
  195.             }
  196.             else {
  197.                 printf("\nSkipped %s--no read/write access",f.achName);
  198.                 logf("Skipped %s--no read/write access",f.achName);
  199.             }
  200.  
  201. SkipPkt:
  202.  
  203.             num_matches = 1;
  204.         } while(!DosFindNext(search_handle,&f,sizeof(FILEFINDBUF),
  205.                              &num_matches));
  206.         DosFindClose(search_handle);
  207.     }
  208.  
  209. DoArchives:
  210.  
  211.     while(x < MAXARCEXTS) {
  212.         search_handle = 1;
  213.         num_matches = 1;
  214.         sprintf(buffer,"%s/*.%s?",inbound,arcext[x]);
  215.         if(!DosFindFirst(buffer,&search_handle,0,&f,
  216.           sizeof(FILEFINDBUF),&num_matches,0L)) {
  217.             do {
  218.  
  219.                 if(!f.cbFile) goto NextOne;
  220.                 if(!stricmp(arcfile,f.achName)) goto NextOne;
  221.                 sprintf(buffer,"%s/%s",inbound,f.achName);
  222.                 if(access(buffer,6)) {
  223.                     printf("\nSkipped %s--no read/write access",f.achName);
  224.                     logf("Skipped %s--no read/write access",f.achName);
  225.                     goto NextOne;
  226.                 }
  227.  
  228.                 DosQFSInfo(0,1,&sz,sizeof(sz));
  229.                 diskspace = sz.avail * sz.sectors * sz.bytes;
  230.                 if(diskspace < f.cbFile * 3L) {
  231.                     printf("\nProbably insufficient diskspace to process \"%s\"",f.achName);
  232.                     printf("\nFilesize: %ld  Diskspace: %ld",f.cbFile,diskspace);
  233.                     logf("Probably insufficient diskspace to process \"%s\"",f.achName);
  234.                     logf("Filesize: %ld  Diskspace: %ld",f.cbFile,diskspace);
  235.                     goto NextOne;
  236.                 }
  237.  
  238.                 printf("\nAttempting to crack archive \"%s\"\n",f.achName);
  239.                 switch_to(inbound);
  240.                 strcpy(arcfile,f.achName);
  241.                 sprintf(buffer,"%s %s\\%s *.PKT",unarchive,inbound,f.achName);
  242.                 system(buffer);
  243.                 switch_back();
  244.  
  245.                 /* This godawful kludge so it'll run under DOS */
  246.  
  247.                 DosFindClose(search_handle);
  248.  
  249.                 sprintf(buffer,"%s/*.PKT",inbound);
  250.                 search_handle = 1;
  251.                 num_matches = 1;
  252.                 if(!DosFindFirst(buffer,&search_handle,0,&f,
  253.                   sizeof(FILEFINDBUF),&num_matches,0L)) {
  254.                     DosFindClose(search_handle);
  255.                     sprintf(buffer,"%s/%s",inbound,arcfile);
  256.                     my_unlink(buffer);
  257.                     goto DoPackets;
  258.                 }
  259.                 else {
  260.                     printf("\nUnarchive attempt failed");
  261.                     logf("Unarchive of \"%s\" failed",f.achName);
  262.                     goto NextOne;
  263.                 }
  264.  
  265.                 goto DoArchives;
  266. NextOne:
  267.  
  268.                 num_matches = 1;
  269.             } while(!DosFindNext(search_handle,&f,sizeof(FILEFINDBUF),
  270.                                  &num_matches));
  271.             DosFindClose(search_handle);
  272.         }
  273.         x++;
  274.     }
  275.  
  276.     if(dataptr != -1) close(dataptr);
  277.     if(textptr != -1) close(textptr);
  278.  
  279.     sprintf(buffer,"%s/UNKNOWN.$$$",inbound);
  280.     p = &buffer[strlen(buffer) + 1];
  281.     sprintf(p,"%s/UNKNOWN.PKT",inbound);
  282.     my_rename(buffer,p);
  283.  
  284.     report();
  285. }
  286.  
  287.  
  288.  
  289. static void _fastcall report (void) {
  290.  
  291.     GROUP   *currgroup;
  292.     ECHOREC *currecho;
  293.     long    totalmsgs  = 0L;
  294.  
  295.  
  296.     printf("\n");
  297.  
  298.     currgroup = group;
  299.     while(currgroup) {
  300.         if(currgroup->forwarded) {
  301.             totalmsgs += (long)currgroup->forwarded;
  302.             logf("Forwarded %u msg%s for group #%u \"%s\"",
  303.                  currgroup->forwarded,&"s"[currgroup->forwarded == 1],
  304.                  currgroup->areano,currgroup->id);
  305.         }
  306.         if(currgroup->imported) {
  307.             totalmsgs += (long)currgroup->imported;
  308.             logf("Imported %u msg%s into group #%u \"%s\"",
  309.                  currgroup->imported,&"s"[currgroup->imported == 1],
  310.                  currgroup->areano,currgroup->id);
  311.         }
  312.         currgroup = currgroup->next;
  313.     }
  314.  
  315.     currecho = echos;
  316.     while(currecho) {
  317.         if(currecho->imported) {
  318.             totalmsgs += (long)currecho->imported;
  319.             logf("Imported %u msg%s into echo #%u \"%s\"",
  320.                  currecho->imported,&"s"[currecho->imported == 1],
  321.                  currecho->areano,currecho->tag);
  322.         }
  323.         if(currecho->forwarded) {
  324.             logf("Forwarded %u msg%s from echo #%u \"%s\"",
  325.                  currecho->forwarded,&"s"[currecho->forwarded == 1],
  326.                  currecho->areano,currecho->tag);
  327.         }
  328.         currecho = currecho->next;
  329.     }
  330.  
  331.     if(numpassthru) logf("%u echo msg%s in pass-thru area(s)",
  332.                          numpassthru,&"s"[numpassthru == 1]);
  333.  
  334.     if(numechoforwarded) logf("%lu total echomail msg%s were forwarded",
  335.                               numechoforwarded,&"s"[numechoforwarded == 1]);
  336.  
  337.     if(unknownmsgs) logf("%u echo msg%s in unknown area(s) (to UNKNOWN.PKT)",
  338.                          unknownmsgs,&"s"[unknownmsgs == 1]);
  339.     totalmsgs += unknownmsgs;
  340.  
  341.     if(insecuremsgs) logf("%u echo msg%s from unlisted nodes (to INSECURE.$$$)",
  342.                           insecuremsgs,&"s"[insecuremsgs == 1]);
  343.     totalmsgs += insecuremsgs;
  344.  
  345.     if(numdupes) {
  346.         if(!control.keepdupes) logf("%u dupe echo msg%s rejected",
  347.                                     numdupes,&"s"[numdupes == 1]);
  348.         else logf("%u dupe msg%s rejected (to AREDUPES.$$$)",
  349.                   numdupes,&"s"[numdupes == 1]);
  350.     }
  351.     totalmsgs += numdupes;
  352.  
  353.     if(netimported) logf("Imported %u msg%s into #%u netmail",
  354.                           netimported,&"s"[netimported == 1],netarea);
  355.     totalmsgs += netimported;
  356.  
  357.     if(netforwarded) logf("%lu total netmail msg%s forwarded",
  358.                           netforwarded,&"s"[netforwarded == 1]);
  359.  
  360.     totalmsgs += netforwarded;
  361.  
  362.     if(notforwarded) logf("%lu total netmail msg%s *not* forwarded",
  363.                           notforwarded,&"s"[notforwarded == 1]);
  364.  
  365.     if(control.keepnoforwards) logf("(Unforwarded msgs in FORWARD.$$$)");
  366.  
  367.     totalmsgs += netforwarded;
  368.  
  369.     if(numassholes) logf("%u asshole msg%s were not imported",numassholes,
  370.                          &"s"[numassholes == 1]);
  371.  
  372.     totalmsgs += numassholes;
  373.  
  374.     if(totalmsgs) {
  375.         logf("Total msgs processed: %lu",totalmsgs);
  376.     }
  377. }
  378.  
  379.  
  380.  
  381. static int _fastcall crack_pkt (char *pktname) {
  382.  
  383.     int           fp,temp,islocal,isass;
  384.     long          len;
  385.     char          *buff,*text,*lastassarea = NULL,*lastdupearea = NULL,*p;
  386.     word          buflen,msgsprocd = 0,x;
  387.     XMSG          msg;
  388.     PKTHDR        pi;
  389.     OLDPKTHDR     *opi;
  390.     ADDR          *ainfo,*achk,pktaddr,nchk;
  391.     ECHOREC       *currecho = NULL;
  392.     GROUP         *currgroup = NULL;
  393.     ASSHOLE       *anass;
  394.     TONAMES       *aname;
  395.  
  396.  
  397.     printf("\nProcessing packet \"%s\"",pktname);
  398.     buff = strdup(pktname);
  399.     if(!buff) return -2;
  400.     pktname = buff;
  401.  
  402.     fp = sopen(pktname,O_RDONLY | O_BINARY,SH_DENYWR);
  403.     if(fp == -1) {
  404.         printf("\nCouldn't open packet \"%s\"\n",pktname);
  405.         logf("Couldn't open packet \"%s\"\n",pktname);
  406.         my_free(pktname);
  407.         return -1;      /* Return Can't Open */
  408.     }
  409.     lseek(fp,0L,SEEK_END);    /* Get packet size */
  410.     len = tell(fp);
  411.     if(len <= (long)sizeof(PKTHDR) + 2L) {
  412.         close(fp);
  413.         my_unlink(pktname);
  414.         printf("\nShort packet discarded");
  415.         my_free(pktname);
  416.         return 0;            /* Ignore 'short' packet */
  417.     }
  418.  
  419.     if((len - (long)sizeof(PKTHDR)) < 65500L)
  420.       buflen = (word)((len - (long)sizeof(PKTHDR)) + 1L);
  421.     else buflen = 65501U;     /* Set minimum buff length */
  422.  
  423.     buff = (char *)malloc(buflen + 1);        /* Allocate text buff */
  424.     if(!buff) {
  425.         close(fp);
  426.         my_free(pktname);
  427.         printf("\nOut of memory\n");
  428.         return -2;        /* Return OOM */
  429.     }
  430.  
  431.     memset(&pi,0,sizeof(PKTHDR));
  432.     lseek(fp,0L,SEEK_SET);
  433.     lseek(fp,0L,SEEK_SET);
  434.     read(fp,&pi,sizeof(PKTHDR)); /* Get packet header */
  435.  
  436.     if(pi.version != 2) {   /* not type 2; can't handle it */
  437.         return -4;
  438.     }
  439.  
  440.     opi = (OLDPKTHDR *)π
  441.     if(pi.subver == 2) {         /* it's a type 2.2 (FSC-0045) */
  442.         pktaddr.zone = pi.ozone;
  443.         pktaddr.net = pi.onet;
  444.         pktaddr.node = pi.onode;
  445.         pktaddr.point = pi.opoint;
  446.         if(pi.odomain) pktaddr.domain = strdup(pi.odomain);
  447.         else pktaddr.domain = NULL;
  448.         if(pktaddr.domain) {
  449.             p = strchr(pktaddr.domain,'.');
  450.             if(p) {
  451.                 *p = 0;
  452.                 if(!*pktaddr.domain) {
  453.                     my_free(pktaddr.domain);
  454.                     pktaddr.domain = NULL;
  455.                 }
  456.             }
  457.         }
  458.         pktaddr.next = NULL;
  459.         if(pktaddr.zone != 0 || pktaddr.net != 0 || pktaddr.node != 0 ||
  460.           pktaddr.point != 0 || (pktaddr.domain && *pktaddr.domain))
  461.             guess_rest(&pktaddr,myaddr);
  462.     }
  463.     else {
  464.         pktaddr.zone = opi->qm_orig_zone;
  465.         pktaddr.net = opi->orig_net;
  466.         pktaddr.node = opi->orig_node;
  467.         pktaddr.point = opi->orig_point;
  468.         if(!pktaddr.zone) pktaddr.zone = opi->orig_zone;
  469.         pktaddr.domain = NULL;
  470.         pktaddr.next = NULL;
  471.         if(pktaddr.zone != 0 || pktaddr.net != 0 || pktaddr.node != 0 ||
  472.            pktaddr.point != 0 || (pktaddr.domain && *pktaddr.domain))
  473.             guess_rest(&pktaddr,myaddr);
  474.     }
  475.  
  476.     logf("Processing packet \"%s\" from %u:%u/%u.%u@%s",pktname,
  477.           pktaddr.zone,pktaddr.net,pktaddr.node,pktaddr.point,
  478.           ((pktaddr.domain) ? pktaddr.domain : ""));
  479.  
  480.     printf(" from %u:%u/%u.%u@%s",pktaddr.zone,pktaddr.net,
  481.            pktaddr.node,pktaddr.point,
  482.            ((pktaddr.domain) ? pktaddr.domain : ""));
  483.  
  484.     printf("\n\x1b[K");
  485.  
  486.     while(!eof(fp)) {
  487.  
  488. ContHere:
  489.  
  490.         islocal = isass = 0;
  491.         temp = get_msg(buflen,buff,&text,fp,&msg);
  492.         if(temp == -3) {
  493.             continue;
  494.         }
  495.         if(temp == -1) {
  496.             close(fp);
  497.             my_free(buff);
  498.             my_unlink(pktname);
  499.             my_free(pktname);
  500.             printf("\x1b[s\x1b[1;1H\x1b[KMinor error\x1b[u");
  501.             logf("Encountered minor error");
  502.             return -3;         /* Return 'minor' error */
  503.         }
  504.         if(temp < 0) break;    /* End of packet */
  505.         msgsprocd++;
  506.         if(!text || !*text) {
  507.             printf("\x1b[s\x1b[1;1H\x1b[KNULL message discarded.\x1b[u");
  508.             continue;          /* NULL message */
  509.         }
  510.  
  511.         if(!temp) {
  512.             if(!area || !*area) {   /* is netmail */
  513.                 nchk.zone = msg.d_zone;
  514.                 nchk.net = msg.dest_net;
  515.                 nchk.node = msg.dest;
  516.                 nchk.point = msg.d_point;
  517.                 if(*to_domain) nchk.domain = strdup(to_domain);
  518.                 else nchk.domain = NULL;
  519.                 nchk.next = NULL;
  520.                 guess_rest(&nchk,myaddr);
  521.                 ainfo = myaddr;
  522.                 while(ainfo) {
  523.                     if(ainfo->zone == nchk.zone && ainfo->net == nchk.net &&
  524.                       ainfo->node == nchk.node && ainfo->point == nchk.point &&
  525.                       (!nchk.domain || !strnicmp(nchk.domain,ainfo->domain,8))) {
  526.  
  527.                         if(tonames) {
  528.                             aname = tonames;
  529.                             while(aname) {
  530.                                 if(!stricmp(msg.to,aname->to)) {
  531.                                     if(aname->msg) {    /* export as *.MSG */
  532.                                         make_message(text,&msg);
  533.                                     }
  534.                                     else if(aname->route) { /* forward somewhere else */
  535.                                         msg.dest = aname->addr->node;
  536.                                         msg.dest_net = aname->addr->net;
  537.                                         msg.d_zone = aname->addr->zone;
  538.                                         msg.d_point = aname->addr->point;
  539.                                         if(aname->addr->domain) strncpy(to_domain,aname->addr->domain,38);
  540.                                         else *to_domain = 0;
  541.                                         to_domain[38] = 0;
  542.                                         forward(text,&msg,NULL,NULL,aname->addr);
  543.                                     }
  544.                                     else if(aname->prog) {  /* spawn program as */
  545.                                                             /* prog *.MSG-filename */
  546.                                         word msgno;
  547.                                         char obj[18];
  548.                                         union rr {
  549.                                             long lret;
  550.                                             struct ints {
  551.                                                 int  cpid;
  552.                                                 int  cret;
  553.                                             } i;
  554.                                         } ret;
  555.                                         char *args[5];
  556.  
  557.                                         msgno = make_message(text,&msg);
  558.                                         if(!msgno) {
  559.                                             logf("Couldn't create *.MSG file for To: \"%s\"...imported",msg.to);
  560.                                             break;
  561.                                         }
  562.                                         if(putmsgs) sprintf(buffer,"%s/%u.MSG",putmsgs,msgno);
  563.                                         else sprintf(buffer,"%u.MSG",msgno);
  564.                                         if(strstr(aname->prgname,".CMD")) {
  565.                                             args[0] = "CMD.EXE";
  566.                                             msgno = 1;
  567.                                         }
  568.                                         else msgno = 0;
  569.                                         args[msgno++] = aname->prgname;
  570.                                         args[msgno++] = buffer;
  571.                                         args[msgno] = "";
  572.                                         if(!DosExecPgm(obj,18,4,&args[1],NULL,(long *)&ret.lret,args[0])) {
  573.                                             printf("Spawned \"%s\" detached\n",aname->prgname);
  574.                                             logf("Spawned \"%s\" detached",aname->prgname);
  575.                                         }
  576.                                         else logf("Couldn't spawn \"%s\"",aname->prgname);
  577.                                     }
  578.                                     goto ContHere;
  579.                                 }
  580.                                 aname = aname->next;
  581.                             }
  582.                         }
  583.  
  584.                         netimported++;
  585.                         temp = import(text,&msg,NULL,NULL,msgsprocd);  /* import netmail */
  586.                         break;
  587.                     }
  588.                     if(ainfo->zone == nchk.zone && ainfo->net == nchk.net &&
  589.                       (!nchk.domain || !strnicmp(nchk.domain,ainfo->domain,8))) {
  590.                         islocal = 1;
  591.                     }
  592.                     ainfo = ainfo->next;
  593.                 }
  594.                 my_free(nchk.domain);
  595.                 if(!ainfo) {    /* forward netmail */
  596.                     if(islocal) {
  597.                         if(!control.nolocalfor) {
  598.                             printf("\nForwarding \"local\" msg");
  599.                             netforwarded++;
  600.                             forward(text,&msg,NULL,NULL,&pktaddr);
  601.                             printf("\nForwarded message addr to %u:%u/%u.%u@%s",
  602.                                    msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  603.                                    to_domain);
  604.                             logf("Forwarded message addr to %u:%u/%u.%u@%s",
  605.                                  msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  606.                                  to_domain);
  607.                         }
  608.                         else if(!control.keepnoforwards) {
  609.                             printf("\nTrashed message addr to %u:%u/%u.%u@%s",
  610.                                     msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  611.                                     to_domain);
  612.                             logf("Trashed message addr to %u:%u/%u.%u@%s",
  613.                                   msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  614.                                   to_domain);
  615.                         }
  616.                         else {
  617.                             is_notforwarded(text,&msg);
  618.                             notforwarded++;
  619.                         }
  620.                     }
  621.                     else {
  622.                         if(!control.noforward) {
  623.                             netforwarded++;
  624.                             printf("\nForwarding \"foreign\" msg");
  625.                             forward(text,&msg,NULL,NULL,&pktaddr);
  626.                             printf("\nForwarded message addr to %u:%u/%u.%u@%s",
  627.                                    msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  628.                                    to_domain);
  629.                             logf("Forwarded message addr to %u:%u/%u.%u@%s",
  630.                                  msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  631.                                  to_domain);
  632.                         }
  633.                         else if(!control.keepnoforwards) {
  634.                             printf("\nTrashed message addr to %u:%u/%u.%u@%s",
  635.                                     msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  636.                                     to_domain);
  637.                             logf("Trashed message addr to %u:%u/%u.%u@%s",
  638.                                   msg.d_zone,msg.dest_net,msg.dest,msg.d_point,
  639.                                   to_domain);
  640.                         }
  641.                         else {
  642.                             is_notforwarded(text,&msg);
  643.                             notforwarded++;
  644.                         }
  645.                     }
  646.                 }
  647.             }
  648.  
  649.             else {      /* is either echo or groupmail */
  650.  
  651.                 if(grunged_area) {
  652.                     if(pktaddr.zone != 0 || pktaddr.net != 0 || pktaddr.node != 0 ||
  653.                     pktaddr.point != 0 || (pktaddr.domain && *pktaddr.domain))
  654.                       bitch_and_moan(&pktaddr,area);
  655.                 }
  656.                 if(grunged_seenbys) {
  657.                     if(pktaddr.zone != 0 || pktaddr.net != 0 || pktaddr.node != 0 ||
  658.                     pktaddr.point != 0 || (pktaddr.domain && *pktaddr.domain))
  659.                       bitch_and_moan_again(&pktaddr,area);
  660.                 }
  661.  
  662.                 currecho = echos;
  663.                 while(currecho) {
  664.                     if(!stricmp(currecho->tag,area)) {
  665.                         break;
  666.                     }
  667.                     currecho = currecho->next;
  668.                 }
  669.                 if(!currecho) {
  670.                     currgroup = group;
  671.                     while(currgroup) {
  672.                         if(!stricmp(currgroup->id,area)) {
  673.                             break;
  674.                         }
  675.                         currgroup = currgroup->next;
  676.                     }
  677.                 }
  678.                 if(currecho) {  /* is echomail */
  679.                     achk = currecho->addr;
  680.                     if(pktaddr.zone != 0 || pktaddr.net != 0 || pktaddr.node != 0 ||
  681.                        pktaddr.point != 0 || (pktaddr.domain && *pktaddr.domain)) {
  682.                         while(achk) {
  683.                             if(achk->zone == pktaddr.zone && achk->net == pktaddr.net &&
  684.                               achk->node == pktaddr.node && achk->point == pktaddr.point &&
  685.                               (!achk->domain || !strnicmp(pktaddr.domain,achk->domain,8))) {
  686.                                 break;
  687.                             }
  688.                             achk = achk->next;
  689.                         }
  690.                     }
  691.  
  692.                     if(!control.nodupes && msgidcrc && serialno) {
  693.                         if(lastdupearea != currecho->tag) {
  694.                             load_dupes(currecho->areano);
  695.                             lastdupearea = currecho->tag;
  696.                         }
  697.                         if(dupes) {
  698.                             for(x = 0;x < maxdupes;x++) {
  699.                                 if(dupes[x].msgidcrc && dupes[x].serialno) {
  700.                                     if(dupes[x].msgidcrc == msgidcrc &&
  701.                                       dupes[x].serialno == serialno) {
  702.                                         founddupes = 1;
  703.                                         numdupes++;
  704.                                         if(control.keepdupes) {
  705.                                             isadupe(text,&msg,area);
  706.                                         }
  707.                                         goto ContHere;
  708.                                     }
  709.                                 }
  710.                             }
  711.                         }
  712.                     }
  713.  
  714.                     anass = NULL;
  715.                     if(!control.noassholes) {
  716.                         if(lastassarea != currecho->tag) {
  717.                             load_assholes(currecho->areano);
  718.                             lastassarea = currecho->tag;
  719.                         }
  720.                         if(assholes) {
  721.                             anass = assholes;
  722.                             while(anass && anass->name) {
  723.                                 if(anass->subj) {
  724.  
  725.                                     char *p;
  726.  
  727.                                     p = msg.subj;
  728.                                     while(!strnicmp(p,"RE:",3)) {
  729.                                         p += 3;
  730.                                         while(*p && *p == ' ') p++;
  731.                                     }
  732.                                     if(!stricmp(p,anass->name)) {
  733.                                         if(anass->del || anass->noin) {
  734.                                             isass = 1;
  735.                                             break;
  736.                                         }
  737.                                     }
  738.                                 }
  739.                                 else {
  740.                                     if(anass->from) {
  741.                                         if(!stricmp(msg.from,anass->name)) {
  742.                                             if(anass->del || anass->noin) {
  743.                                                 isass = 1;
  744.                                                 break;
  745.                                             }
  746.                                         }
  747.                                     }
  748.                                     if(anass->to) {
  749.                                          if(!stricmp(msg.to,anass->name)) {
  750.                                             if(anass->del || anass->noin) {
  751.                                                 isass = 1;
  752.                                                 break;
  753.                                             }
  754.                                         }
  755.                                     }
  756.                                 }
  757.                                 anass = anass->next;
  758.                             }
  759.                         }
  760.                     }
  761.  
  762.                     if(isass) numassholes++;
  763.  
  764.                     if((!achk && currecho->addr) && !isass) {     /* not from listed node */
  765.                         insecure(text,&msg,area);
  766.                     }
  767.                     else {
  768.                         if(dupes && !control.nodupes && msgidcrc && serialno) {
  769.                             founddupes = 1;
  770.                             dupes[nextdupe].msgidcrc = msgidcrc;
  771.                             dupes[nextdupe].serialno = serialno;
  772.                             nextdupe++;
  773.                             if(nextdupe >= maxdupes) nextdupe = 0;
  774.                         }
  775.                         if(currecho->addr && currecho->addr->next) {  /* feeding more than one node */
  776.                             if(!isass || (!anass || !anass->del) || !control.assexport) {
  777.                                 currecho->forwarded++;
  778.                                 numechoforwarded++;
  779.                                 temp = forward(text,&msg,currecho,NULL,&pktaddr);
  780.                             }
  781.                         }
  782.                         if(!isass) {
  783.                             currecho->imported++;
  784.                             temp = import(text,&msg,currecho,NULL,msgsprocd);
  785.                         }
  786.                     }
  787.                 }
  788.                 else if(currgroup) {    /* is groupmail */
  789.                     if(currgroup->uplink) { /* forward toward topstar */
  790.                         currgroup->forwarded++;
  791.                         forward(text,&msg,NULL,currgroup,&pktaddr);
  792.                     }
  793.                     else temp = import(text,&msg,NULL,currgroup,msgsprocd); /* we are topstar */
  794.                 }
  795.                 else {  /* unknown area */
  796.                     unknown(text,&msg,area);
  797.                 }
  798.             }
  799.         }
  800.     }
  801.     close(fp);             /* Close packet */
  802.     my_unlink(pktname);    /* Get rid of packet after unpacking */
  803.     my_free(buff);
  804.     my_free(pktname);
  805.     if(assholes) free_assholes();
  806.     if(dupes) free_dupes();
  807.     return 0;              /* Return success */
  808. }
  809.  
  810.  
  811.  
  812.  
  813. static int _fastcall import (char *buff,XMSG *xmsg,ECHOREC *currecho,
  814.                              GROUP *currgroup,word msgnum) {
  815.  
  816.     /* Put msg in XBBS base */
  817.  
  818.     static  word lastarea = 0;
  819.     char    *hold;
  820.     word    temp,thisarea = 0,x;
  821.     time_t  tt;
  822.     struct  tm *t;
  823.     long    pos;
  824.  
  825.  
  826.     if(!currecho && !currgroup) {
  827.         thisarea = netarea;
  828.         xmsg->m_attr |= MSGNET;
  829.     }
  830.     else {
  831.         if(currecho) thisarea = currecho->areano;
  832.         else if(currgroup) thisarea = currgroup->areano;
  833.         xmsg->m_attr |= MSGECHO;
  834.     }
  835.  
  836.     if(!thisarea) {
  837.         numpassthru++;
  838.         return 0;    /* pass-thru */
  839.     }
  840.  
  841.     if(lastarea != thisarea) {  /* close msg areas, reopen */
  842.         printf("\n\x1b[K");
  843.         if(open_msg_files(thisarea)) return -1;
  844.         lastarea = thisarea;
  845.     }
  846.  
  847.     x = 0;
  848.     while(x < 50) {
  849.         if(lseek(textptr,0L,SEEK_END) != -1L) break;
  850.         DosSleep(100L);
  851.         x++;
  852.     }
  853.     if(x >= 50) {
  854.         printf("\nLocking conflict; can't import msg\n");
  855.         return -1;
  856.     }
  857.     locking(textptr,LK_LOCK,65535L);
  858.     xmsg->start = tell(textptr);
  859.  
  860.     if(packsize && xmsg->length > packsize && !control.keepsbs && !control.keeppath) {
  861.  
  862.         temp = strlen(buff);
  863.         if(temp > 65100U) {
  864.             buff[65099U] = 0;
  865.             temp = 65100U;
  866.         }
  867.         hold = (char *)malloc(temp + 256);
  868.         if(!hold) {
  869.             write(textptr,buff,temp);
  870.         }
  871.         else {
  872.             hold = pack_msg(hold,xmsg);
  873.             if(!hold) {
  874.                write(textptr,buff,temp);
  875.             }
  876.             else {
  877.                 xmsg->m_attr |= MSGPACKED;
  878.                 write(textptr,hold,xmsg->length);
  879.             }
  880.             my_free(hold);
  881.        }
  882.     }
  883.     else {
  884.         if(control.keeppath) {
  885.             xmsg->length = 0;
  886.             if(newpath) {
  887.                 xmsg->length += write(textptr,newpath,strlen(newpath));
  888.                 xmsg->length += write(textptr,"\r",1);
  889.             }
  890.         }
  891.         xmsg->length += write(textptr,buff,strlen(buff));
  892.         if(control.keepsbs) {
  893.             if(seenby) {
  894.                 xmsg->length += write(textptr,"\r",1);
  895.                 xmsg->length += write(textptr,seenby,strlen(seenby));
  896.             }
  897.         }
  898.         if(control.keeppath) {
  899.             if(pathline) {
  900.                 xmsg->length += write(textptr,"\r",1);
  901.                 xmsg->length += write(textptr,pathline,strlen(pathline));
  902.             }
  903.         }
  904.     }
  905.  
  906.     write(textptr,"\0",2);
  907.     lseek(textptr,xmsg->start,SEEK_SET);
  908.     locking(textptr,LK_UNLCK,65535L);
  909.  
  910.     tt = time(NULL);
  911.     t = localtime(&tt);
  912.     xmsg->indate[0] = (char)(t->tm_year - 89);
  913.     xmsg->indate[1] = (char)(t->tm_mon + 1);
  914.     xmsg->indate[2] = (char)t->tm_mday;
  915.     xmsg->indate[3] = 0;
  916.  
  917.     if(currgroup) { /* set up attribs so msg can be scanned out later */
  918.         printf("#%u (%u) -> group \"%s\"\r",msgnum,currgroup->imported,
  919.                currgroup->id);
  920.         xmsg->m_attr &= (~(MSGDELETED | MSGGSCAN | MSGSCANNED));
  921.         xmsg->attr |= MSGLOCAL;
  922.         xmsg->attr &= (~(MSGSENT | MSGREAD | MSGCRASH | MSGKILL | MSGORPHAN));
  923.     }
  924.     else {  /* set up attribs so msg is never reexported */
  925.         if(currecho)
  926.           printf("#%u (%u) -> echo \"%s\"\r",msgnum,currecho->imported,
  927.                  currecho->tag);
  928.         else printf("#%u (%u) -> netmail\r",msgnum,netimported);
  929.         xmsg->attr |= MSGORPHAN;
  930.         xmsg->attr &= (~MSGLOCAL);
  931.     }
  932.  
  933.     xmsg->length++;
  934.  
  935.     x = 0;
  936.     while(x < 50) {
  937.         if(lseek(dataptr,0L,SEEK_END) != -1L) break;
  938.         DosSleep(100L);
  939.         x++;
  940.     }
  941.     if(x >= 50) {
  942.         printf("\nLocking conflict; can't import msg\n");
  943.         return -1;
  944.     }
  945.     locking(dataptr,LK_LOCK,(long)sizeof(XMSG));
  946.     pos = tell(dataptr);
  947.     write(dataptr,xmsg,sizeof(XMSG));
  948.     lseek(dataptr,pos,SEEK_SET);
  949.     locking(dataptr,LK_UNLCK,(long)sizeof(XMSG));
  950.  
  951.     return 0;
  952. }
  953.  
  954.  
  955.  
  956.  
  957. static int _fastcall get_msg (word buflen,char *buff,char **text,
  958.                               int fp,XMSG *xmsg) {
  959.  
  960.     char *p,*endptr,*tempo,first_grunged = 0;
  961.     long pos;
  962.     word len,*temp,chk;
  963.  
  964.  
  965. Again:
  966.  
  967.     grunged_seenbys = grunged_area = grunged_date = 0;
  968.     msgidcrc = serialno = 0L;
  969.     newpath = NULL;
  970.     memset(xmsg,0,sizeof(XMSG));
  971.     *to_domain = 0;
  972.     *from_domain = 0;
  973.     if(eof(fp)) return -2;
  974.     pos = tell(fp);
  975.     chk = read(fp,buff,buflen);
  976.     if(!chk || chk == 65535U) return -2;
  977.     buff[buflen] = 0;
  978.     p = buff;
  979.     if(*p != (char)'\02' || p[1] != (char)'\0') {
  980.         if(eof(fp) || (*p == (char)'\0' && p[1] == (char)'\0')) return -2;
  981.         while(*p != (char)'\02' && p < (buff + buflen)) {
  982.             p++;
  983.             pos++;
  984.         }
  985.         lseek(fp,pos,SEEK_SET);
  986.         if(first_grunged) {
  987.             logf("Hmph.  Grunged packet...");
  988.             first_grunged++;
  989.         }
  990.         goto Again;
  991.     }
  992.     p += 2;
  993.     temp = (word *)p;
  994.     xmsg->orig = *temp;
  995.     p += 2;
  996.     temp = (word *)p;
  997.     xmsg->dest = *temp;
  998.     p += 2;
  999.     temp = (word *)p;
  1000.     xmsg->orig_net = *temp;
  1001.     p += 2;
  1002.     temp = (word *)p;
  1003.     xmsg->dest_net = *temp;
  1004.     p += 2;
  1005.     temp = (word *)p;
  1006.     xmsg->attr = *temp;
  1007.     p += 2;
  1008.     xmsg->cost = 0;
  1009.     p += 2;
  1010.     strncpy(xmsg->date,p,20);
  1011.     xmsg->date[19] = 0;
  1012.     while(*p) p++;   /* <--This goddamn kludge thanks to QMail, the broken wonder */
  1013.     p++;
  1014.     strncpy(xmsg->to,p,36);
  1015.     xmsg->to[35] = 0;
  1016.     while(*p) p++;
  1017.     p++;
  1018.     strncpy(xmsg->from,p,36);
  1019.     xmsg->from[35] = 0;
  1020.     while(*p) p++;
  1021.     p++;
  1022.     strncpy(xmsg->subj,p,64);
  1023.     xmsg->subj[63] = 0;
  1024.     while(*p) p++;
  1025.     p++;
  1026.     *text = p;
  1027.     while(*p) p++;
  1028.     p++;                            /* Should be start of next msg */
  1029.     endptr = p;
  1030.     pos += (long)(endptr - buff);
  1031.     lseek(fp,pos,SEEK_SET);            /* Now positioned to start of next msg */
  1032.     if(!*xmsg->to && !*xmsg->from && !*xmsg->subj) {    /* grunged msg */
  1033.         return -3;
  1034.     }
  1035.     len = strlen(*text);
  1036.     if(!len) {
  1037.         return -3;
  1038.     }
  1039.  
  1040.     if(strlen(xmsg->date) < 19) {
  1041.  
  1042.         int x;
  1043.  
  1044.         if(control.delbaddate) return -3;  /* ignore broken dates */
  1045.         grunged_date = 1;
  1046.         for(x = 0; x < 19;x++) if(!xmsg->date[x]) xmsg->date[x] = 'Q';
  1047.     }
  1048.  
  1049.     p = *text;
  1050.     while (*p) {    /* Strip linefeeds and soft cr's FAST */
  1051.         if(*p == '\x8d' || *p == '\n') {
  1052.             memmove(p,&p[1],len - (word)((long)p - (long)*text));
  1053.             len--;
  1054.             if(!len) break;
  1055.             continue;
  1056.         }
  1057.         p++;
  1058.     }
  1059.  
  1060.     if(!strnicmp(*text,"\01AREA:",6)) {
  1061.         tempo = *text;
  1062.         memmove(tempo,&tempo[1],strlen(tempo));
  1063.         grunged_area = 1;
  1064.     }
  1065.  
  1066.     if(!strnicmp(*text,"AREA:",5)) { /* Echo area tag */
  1067.         area = *text;
  1068.         while(**text && **text != '\r') {
  1069.             (*text)++;
  1070.         }
  1071.         if(**text) {
  1072.             **text = 0;                  /* area now = area tag line */
  1073.             (*text)++;                     /* text = true start of msg body if any */
  1074.         }
  1075.         while(**text == '\r' && **text) (*text)++; /* Skip leading cr's in body */
  1076.         area += 5;
  1077.         lstrip(area);
  1078.         rstrip(area);                    /* Points directly to tag */
  1079.     }
  1080.     else area = NULL;
  1081.  
  1082.     if (area) {             /* Do ECHO specific BS */
  1083.  
  1084.         origin = pathline = seenby = kludge = NULL;
  1085.  
  1086.         tempo = *text;     /* They oughta outlaw EID's */
  1087.         while ((tempo = strstr(tempo,"\01EID:")))
  1088.           memmove(tempo,strchr(&tempo[1],'\r'),strlen(strchr(&tempo[1],'\r'))+1);
  1089.  
  1090.         tempo = *text;     /* and VIA's */
  1091.         while ((tempo = strstr(tempo,"\01VIA")))
  1092.           memmove(tempo,strchr(&tempo[1],'\r'),strlen(strchr(&tempo[1],'\r'))+1);
  1093.  
  1094.         while(**text == '\r' && **text) (*text)++; /* Skip leading cr's in body */
  1095.  
  1096.         if((tempo = strstr(*text,"\01NPTH "))) { /* isolate new path */
  1097.             if(tempo == *text || (tempo > buff && *(tempo - 1) == '\r'))
  1098.               newpath = tempo;
  1099.             tempo = newpath;
  1100.             if(tempo) {
  1101.                 while((tempo = strchr(tempo,'\r'))) {
  1102.                     if(strnicmp(&tempo[1],"\01NPTH ",6)) tempo++;
  1103.                     else {
  1104.                         *tempo = 0;
  1105.                         tempo++;
  1106.                         *text = tempo;
  1107.                         while(**text == '\r' && **text)
  1108.                           (*text)++; /* Skip leading cr's in body */
  1109.                         break;
  1110.                     }
  1111.                 }
  1112.             }
  1113.         }
  1114.  
  1115.         if(!strncmp(*text," * Origin: ",11)) **text = 0;    /* Nothin' but origin */
  1116.  
  1117.         origin = strstr(*text,"\r * Origin:");  /* find origin line */
  1118.         if (origin) {       /* Ain't one; oh, well, screw it */
  1119.             while(tempo = strstr(&origin[1],"\r * Origin:")) origin = tempo; /* Find last */
  1120.             pathline = strstr(origin,"\r\01PATH:");   /* Find the PATH line */
  1121.             seenby = strstr(origin,"\rSEEN-BY:"); /* Find start of SEEN-BYs */
  1122.                         if (!seenby) {
  1123.                                 seenby = strstr(origin,"\r\01SEEN-BY:");
  1124.                                 if(seenby) {
  1125.                                         grunged_seenbys = 1;
  1126.                                         while(tempo = strstr(seenby,"\r\01SEEN-BY:")) {
  1127.                                                 memmove(seenby,&seenby[1],strlen(seenby));
  1128.                                         }
  1129.                                 }
  1130.                         }
  1131.             if(pathline) {
  1132.                 *pathline = 0;
  1133.                 pathline++;
  1134.             }
  1135.             if(seenby) {
  1136.                 *seenby = 0;
  1137.                 seenby++;
  1138.             }
  1139.         }
  1140.     }
  1141.  
  1142.     {        /* Fill in header address info from kludges */
  1143.  
  1144.         char message[MAXKLUDGE];
  1145.  
  1146.         if ((p=strstr(*text,"\01FMPT "))) {
  1147.             strncpy(message,p,MAXKLUDGE);
  1148.             message[MAXKLUDGE-1] = 0;
  1149.             p = message;
  1150.             xmsg->o_point = (word)atol(&p[5]);
  1151.         }
  1152.  
  1153.         if ((p=strstr(*text,"\01TOPT "))) {
  1154.             strncpy(message,p,MAXKLUDGE);
  1155.             message[MAXKLUDGE-1] = 0;
  1156.             p = message;
  1157.             xmsg->d_point = (word)atol(&p[5]);
  1158.         }
  1159.  
  1160.         if ((p=strstr(*text,"\01INTL "))) {
  1161.             strncpy(message,p,MAXKLUDGE);
  1162.             message[MAXKLUDGE-1] = 0;
  1163.             p = message;
  1164.             strtok(p," :");
  1165.             strtok(0," ");
  1166.             tempo = strtok(0,":");
  1167.             if(tempo) {
  1168.                 if ((word)atol(tempo)) {
  1169.                     xmsg->o_zone = (word)atol(tempo);
  1170.                 }
  1171.             }
  1172.         }
  1173.  
  1174.         if((p = strstr(*text,"\01MSGID: "))) {
  1175.             if((p - 1) < *text || *(p - 1) == '\r') {
  1176.  
  1177.                 ADDR addr;
  1178.                 char temp,*ptr;
  1179.  
  1180.  
  1181.                 memset(&addr,0,sizeof(ADDR));
  1182.                 addr.domain = NULL;
  1183.                 p += 8;
  1184.                 p = skip_white(p);
  1185.  
  1186.                 /* calculate MSGID dupechecking stuff */
  1187.  
  1188.                 tempo = p;
  1189.                 p = skip_nonwhite(p);
  1190.                 if(*p) {
  1191.                     temp = *p;
  1192.                     *p = 0;
  1193.                     msgidcrc = crc32str(tempo,0);
  1194. #ifdef DEBUG
  1195.     logf("MSGID addr: \"%s\"  crc: %ld",tempo,msgidcrc);
  1196. #endif
  1197.                     *p = temp;
  1198.                     p++;
  1199.                     if(*p) {
  1200.                         ptr = p;
  1201.                         serialno = strtol(p,&ptr,16);
  1202. #ifdef DEBUG
  1203.     logf("MSGID serialno: \"%0.8s\"  #: %ld",p,serialno);
  1204. #endif
  1205.                         if((serialno == LONG_MAX || serialno == LONG_MIN) &&
  1206.                           errno == ERANGE) serialno = 0L;
  1207.                     }
  1208.                     p = tempo;
  1209.                 }
  1210.  
  1211.                 if(!parse_addr(&p,&addr,myaddr)) {
  1212.                     if(!addr.zone || !addr.net || !*addr.domain) {
  1213.                         guess_rest(&addr,myaddr);
  1214.                     }
  1215.                     xmsg->o_zone   = addr.zone;
  1216.                     xmsg->orig_net = addr.net;
  1217.                     xmsg->orig     = addr.node;
  1218.                     xmsg->o_point  = addr.point;
  1219.                     strncpy(from_domain,addr.domain,38);
  1220.                     from_domain[38] = 0;
  1221.                     p = strchr(from_domain,'.');
  1222.                     if(p) *p = 0;
  1223.                     my_free(addr.domain);
  1224.                 }
  1225.             }
  1226.         }
  1227.  
  1228.         if((p = strstr(*text,"\01MSGTO: "))) {
  1229.             if((p - 1) < *text || *(p - 1) == '\r') {
  1230.  
  1231.                 ADDR addr;
  1232.  
  1233.                 memset(&addr,0,sizeof(ADDR));
  1234.                 addr.domain = NULL;
  1235.                 p += 8;
  1236.                 p = skip_white(p);
  1237.                 if(!parse_addr(&p,&addr,myaddr)) {
  1238.                     if(!addr.zone || !addr.net || !*addr.domain) {
  1239.                         guess_rest(&addr,myaddr);
  1240.                     }
  1241.                     xmsg->d_zone   = addr.zone;
  1242.                     xmsg->dest_net = addr.net;
  1243.                     xmsg->dest     = addr.node;
  1244.                     xmsg->d_point  = addr.point;
  1245.                     strncpy(to_domain,addr.domain,38);
  1246.                     to_domain[38] = 0;
  1247.                     p = strchr(to_domain,'.');
  1248.                     if(p) *p = 0;
  1249.                     my_free(addr.domain);
  1250.                 }
  1251.             }
  1252.         }
  1253.     }
  1254.  
  1255.     if(!control.keepsbs && !control.keeppath && !control.keepdupes) {
  1256.         p = *text + (strlen(*text) - 1);  /* strip trailing blank lines */
  1257.         while(*p == '\r' && p > *text && *(p-1) == '\r') {
  1258.             *p = 0;
  1259.             p--;
  1260.         }
  1261.         if(seenby || pathline) {
  1262.             p = *text + (strlen(*text) + 1);
  1263.             if(!pathline || seenby < pathline) {
  1264.                 memmove(p,seenby,strlen(seenby) + 1);
  1265.                 if(pathline) {
  1266.                     p = seenby + (strlen(seenby) + 1);
  1267.                     memmove(p,pathline,strlen(pathline) + 1);
  1268.                 }
  1269.             }
  1270.             else {
  1271.                 memmove(p,pathline,strlen(pathline) + 1);
  1272.                 if(seenby) {
  1273.                     p = pathline + (strlen(pathline) + 1);
  1274.                     memmove(p,seenby,strlen(seenby) + 1);
  1275.                 }
  1276.             }
  1277.         }
  1278.     }
  1279.  
  1280.     xmsg->length = strlen(*text);
  1281.     xmsg->m_attr = 0;
  1282.     if(area) xmsg->m_attr |= MSGECHO;        /* Is echo */
  1283.     else xmsg->m_attr |= MSGNET;             /* Is net  */
  1284.     return 0;
  1285. }
  1286.  
  1287.  
  1288.  
  1289. static int _fastcall open_msg_files (word areano) {
  1290.  
  1291.     int tries;
  1292.  
  1293.  
  1294.     if(dataptr != -1) close(dataptr);
  1295.     if(textptr != -1) close(textptr);
  1296.     sprintf(buffer,"%s/XTEXT.%03x",msgdir,areano);
  1297.     tries = 0;
  1298.     do {
  1299.         textptr = sopen(buffer,O_RDWR | O_BINARY | O_CREAT,SH_DENYNO,S_IWRITE | S_IREAD);
  1300.         if(textptr == -1 && errno == EACCES) tries++;
  1301.         else break;
  1302.     } while(tries < 120);
  1303.     sprintf(buffer,"%s/XDATA.%03x",msgdir,areano);
  1304.     tries = 0;
  1305.     do {
  1306.         dataptr = sopen(buffer,O_RDWR | O_BINARY | O_CREAT,SH_DENYNO,S_IWRITE | S_IREAD);
  1307.         if(dataptr == -1 && errno == EACCES) tries++;
  1308.         else break;
  1309.     } while(tries < 120);
  1310.     if(dataptr == -1 || textptr == -1) {
  1311.         if(dataptr != -1) close(dataptr);
  1312.         if(textptr != -1) close(textptr);
  1313.         dataptr = textptr = -1;
  1314.         printf("\nCan't open message base file(s)\n");
  1315.         logf("Can't open message base files");
  1316.         return -1;       /* Error opening message area */
  1317.     }
  1318.  
  1319.     lseek(dataptr,0L,SEEK_END);
  1320.     lseek(textptr,0L,SEEK_END);
  1321.  
  1322.     return 0;
  1323. }
  1324.  
  1325.  
  1326.  
  1327.  
  1328. static int _fastcall forward (char *buff,XMSG *xmsg,ECHOREC *currecho,
  1329.                               GROUP *currgroup,ADDR *pktaddr) {
  1330.  
  1331.     ADDR taddr,faddr,*maddr,*curraddr,*naddr = NULL,*ca,*na;
  1332.     int  fp;
  1333.     SB   *sb = NULL,*opth = NULL,*gate = NULL;
  1334.  
  1335.  
  1336.     if(!currecho && !currgroup) {   /* net msg */
  1337.         taddr.net = xmsg->dest_net;
  1338.         taddr.node = xmsg->dest;
  1339.         taddr.point = xmsg->d_point;
  1340.         taddr.zone = xmsg->d_zone;
  1341.         taddr.domain = strdup(to_domain);
  1342.         faddr.net = xmsg->orig_net;
  1343.         faddr.node = xmsg->orig;
  1344.         faddr.zone = xmsg->o_zone;
  1345.         faddr.domain = strdup(from_domain);
  1346.         taddr.next = faddr.next = NULL;
  1347.         guess_rest(&taddr,myaddr);
  1348.         guess_rest(&faddr,myaddr);
  1349.         fp = open_pkt(&taddr,&faddr,0);
  1350.         if(fp != -1) {
  1351.             write_pkt_msg(fp,xmsg,NULL,NULL,NULL,buff,NULL,NULL);
  1352.         }
  1353.         my_free(faddr.domain);
  1354.         my_free(taddr.domain);
  1355.         if(fp != -1) close(fp);
  1356.         return -1;
  1357.     }
  1358.     else if(currecho) {             /* echo msg */
  1359.         maddr = best_guess(currecho->addr,myaddr);
  1360.         xmsg->o_zone = maddr->zone;
  1361.         xmsg->o_point = maddr->point;
  1362.         xmsg->orig_net = maddr->net;
  1363.         xmsg->orig = maddr->node;
  1364.  
  1365.         if(pathline) {
  1366.             opth = parse_oldpath(pathline);
  1367.             if(!opth) return -1;
  1368.         }
  1369.         if(newpath) {
  1370.             naddr = parse_newpath(newpath);
  1371.             if(!naddr) {
  1372.                 my_free(opth);
  1373.                 return -1;
  1374.             }
  1375.             ca = myaddr;
  1376.             while(ca) {
  1377.                 na = naddr;
  1378.                 while(na) {   /* see if we're already in path */
  1379.                     if(ca->zone == na->zone && ca->net == na->net &&
  1380.                       ca->node == na->node && ca->point == na->point &&
  1381.                       !stricmp(ca->domain,na->domain)) {
  1382.                         my_free(opth);
  1383.                         free_addresses(naddr);
  1384.                         return -1;
  1385.                     }
  1386.                     na = na->next;
  1387.                 }
  1388.                 ca = ca->next;
  1389.             }
  1390.         }
  1391.         if(seenby) {
  1392.             sb = parse_seenbys(seenby,currecho,pktaddr);
  1393.             if(!sb) {
  1394.                 my_free(opth);
  1395.                 if(naddr) free_addresses(naddr);
  1396. printf("\nRED ALERT\n");
  1397.                 return -1;
  1398.             }
  1399.             gate = make_tinysbs(currecho,pktaddr);
  1400.             if(!gate) {
  1401.                 my_free(opth);
  1402.                 if(naddr) free_addresses(naddr);
  1403.                 my_free(sb);
  1404.                 return -1;
  1405.             }
  1406.         }
  1407.         curraddr = currecho->addr;
  1408.         while(curraddr) {
  1409.             if(curraddr->zone == pktaddr->zone && curraddr->net == pktaddr->net &&
  1410.                curraddr->node == pktaddr->node && curraddr->point == pktaddr->point &&
  1411.                (!stricmp(curraddr->domain,pktaddr->domain))) {
  1412.                  goto ContHere;
  1413.             }
  1414.  
  1415.             na = naddr;
  1416.             while(na) {   /* see if he's already in path */
  1417.                 if(curraddr->zone == na->zone && curraddr->net == na->net &&
  1418.                   curraddr->node == na->node && curraddr->point == na->point &&
  1419.                   (!stricmp(curraddr->domain,na->domain))) {
  1420.                     goto ContHere;
  1421.                 }
  1422.                 na = na->next;
  1423.             }
  1424.  
  1425.             fp = open_pkt(curraddr,maddr,0);
  1426.             if(fp != -1) {
  1427.                 xmsg->d_zone = curraddr->zone;
  1428.                 xmsg->dest_net = curraddr->net;
  1429.                 xmsg->dest = curraddr->node;
  1430.                 xmsg->d_point = curraddr->point;
  1431.  
  1432.                 if(curraddr->zone == maddr->zone && !stricmp(curraddr->domain,maddr->domain)) {
  1433.                     write_pkt_msg(fp,xmsg,opth,naddr,maddr,buff,currecho->tag,sb);
  1434.                 }
  1435.                 else {
  1436.                     write_pkt_msg(fp,xmsg,opth,naddr,maddr,buff,currecho->tag,gate);
  1437.                 }
  1438.             }
  1439.             close(fp);
  1440. ContHere:
  1441.             curraddr = curraddr->next;
  1442.         }
  1443.         my_free(opth);
  1444.         if(naddr) free_addresses(naddr);
  1445.         my_free(sb);
  1446.         my_free(gate);
  1447.     }
  1448.     else {                          /* group msg */
  1449.         fp = open_pkt(currgroup->uplink,NULL,0);
  1450.         if(fp != -1) {
  1451.             write_pkt_msg(fp,xmsg,NULL,NULL,NULL,buff,currgroup->id,NULL);
  1452.         }
  1453.         else return -1;
  1454.         close(fp);
  1455.     }
  1456.  
  1457.     return 0;
  1458. }
  1459.  
  1460.  
  1461.  
  1462. static int _fastcall bitch_and_moan (ADDR *addr,char *area) {
  1463.  
  1464.     int         fp;
  1465.     time_t      t;
  1466.     struct tm   *tt;
  1467.     XMSG        xmsg;
  1468.     static char bitch_text[] = "Your node is passing messages with a control-a (^a, CTRL-A, ASCII 1)\r" \
  1469.                                "in front of the AREA: tag in echo \"%s\".\r" \
  1470.                                "Reference FTS-0004 and FSC-0043 for more technical information.\r" \
  1471.                                "Please take the necessary steps to fix this incompatibility.\r\r" \
  1472.                                "    Thanks,\r    XGROUP\r";
  1473.     static char bitch_msg[384];
  1474.  
  1475.  
  1476.     memset(&xmsg,0,sizeof(XMSG));
  1477.     strcpy(xmsg.to,"Sysop");
  1478.     strcpy(xmsg.from,"XGroup");
  1479.         strcpy(xmsg.subj,"Invalid (broken) messages from your node");
  1480.     t = time(NULL);
  1481.     tt = localtime(&t);
  1482.     strftime(bitch_msg,21,"%a %d %b %y %H:%M",tt);
  1483.     strncpy(xmsg.date,bitch_msg,20);
  1484.     xmsg.date[19] = 0;
  1485.     xmsg.d_zone = addr->zone;
  1486.     xmsg.dest = addr->node;
  1487.     xmsg.dest_net = addr->net;
  1488.     xmsg.d_point = addr->point;
  1489.     strncpy(to_domain,addr->domain,8);
  1490.     to_domain[8] = 0;
  1491.     xmsg.attr |= (MSGKILL | MSGLOCAL | MSGPRIVATE);
  1492.  
  1493.     fp = open_pkt(addr,NULL,0);
  1494.     if(fp != -1) {
  1495.         sprintf(bitch_msg,bitch_text,area);
  1496.         write_pkt_msg(fp,&xmsg,NULL,NULL,NULL,bitch_msg,NULL,NULL);
  1497.     }
  1498.     else return -1;
  1499.     close(fp);
  1500.     return 0;
  1501. }
  1502.  
  1503.  
  1504.  
  1505.  
  1506. static int _fastcall bitch_and_moan_again (ADDR *addr,char *area) {
  1507.  
  1508.     int         fp;
  1509.     time_t      t;
  1510.     struct tm   *tt;
  1511.     XMSG        xmsg;
  1512.     static char bitch_text[] = "Your node is passing messages with a control-a (^a, CTRL-A, ASCII 1)\r" \
  1513.                                                              "in front of the SEEN-BY lines in echo \"%s\".\r" \
  1514.                                "Reference FTS-0004 and FSC-0043 for more technical information.\r" \
  1515.                                "Please take the necessary steps to fix this incompatibility.\r\r" \
  1516.                                "    Thanks,\r    XGROUP\r";
  1517.     static char bitch_msg[384];
  1518.  
  1519.  
  1520.     memset(&xmsg,0,sizeof(XMSG));
  1521.     strcpy(xmsg.to,"Sysop");
  1522.     strcpy(xmsg.from,"XGroup");
  1523.         strcpy(xmsg.subj,"Invalid (broken) messages from your node");
  1524.     t = time(NULL);
  1525.     tt = localtime(&t);
  1526.     strftime(bitch_msg,21,"%a %d %b %y %H:%M",tt);
  1527.     strncpy(xmsg.date,bitch_msg,20);
  1528.     xmsg.date[19] = 0;
  1529.     xmsg.d_zone = addr->zone;
  1530.     xmsg.dest = addr->node;
  1531.     xmsg.dest_net = addr->net;
  1532.     xmsg.d_point = addr->point;
  1533.     strncpy(to_domain,addr->domain,8);
  1534.     to_domain[8] = 0;
  1535.     xmsg.attr |= (MSGKILL | MSGLOCAL | MSGPRIVATE);
  1536.  
  1537.     fp = open_pkt(addr,NULL,0);
  1538.     if(fp != -1) {
  1539.         sprintf(bitch_msg,bitch_text,area);
  1540.         write_pkt_msg(fp,&xmsg,NULL,NULL,NULL,bitch_msg,NULL,NULL);
  1541.     }
  1542.     else return -1;
  1543.     close(fp);
  1544.     return 0;
  1545. }
  1546.  
  1547.  
  1548.  
  1549.  
  1550. static int _fastcall unknown (char *buff,XMSG *xmsg,char *area) {
  1551.  
  1552.     ADDR addr;
  1553.     int  fp;
  1554.  
  1555.  
  1556.     addr.zone = addr.net = addr.node = addr.point = 0;
  1557.     addr.domain = NULL;
  1558.     fp = open_pkt(&addr,&addr,IS_UNKNOWN);
  1559.     if(fp != -1) {
  1560.         if(seenby) {
  1561.             seenby--;
  1562.             *seenby = '\r';
  1563.         }
  1564.         if(pathline) {
  1565.             pathline--;
  1566.             *pathline = '\r';
  1567.         }
  1568.         if(newpath && *buff) {
  1569.             newpath[strlen(newpath)] = '\r';
  1570.         }
  1571.         write_pkt_msg(fp,xmsg,NULL,NULL,NULL,buff,area,NULL);
  1572.         unknownmsgs++;
  1573.     }
  1574.     else return -1;
  1575.     close(fp);
  1576.     return 0;
  1577. }
  1578.  
  1579.  
  1580.  
  1581.  
  1582. static int _fastcall insecure (char *buff,XMSG *xmsg,char *area) {
  1583.  
  1584.     ADDR addr;
  1585.     int  fp;
  1586.  
  1587.  
  1588.     addr.zone = addr.net = addr.node = addr.point = 0;
  1589.     addr.domain = NULL;
  1590.     fp = open_pkt(&addr,&addr,IS_INSECURE);
  1591.     if(fp != -1) {
  1592.         if(seenby) {
  1593.             seenby--;
  1594.             *seenby = '\r';
  1595.         }
  1596.         if(pathline) {
  1597.             pathline--;
  1598.             *pathline = '\r';
  1599.         }
  1600.         if(newpath && *buff) {
  1601.             newpath[strlen(newpath)] = '\r';
  1602.         }
  1603.         write_pkt_msg(fp,xmsg,NULL,NULL,NULL,buff,area,NULL);
  1604.         insecuremsgs++;
  1605.     }
  1606.     else return -1;
  1607.     close(fp);
  1608.     return 0;
  1609. }
  1610.  
  1611.  
  1612.  
  1613.  
  1614. static int _fastcall isadupe (char *buff,XMSG *xmsg,char *area) {
  1615.  
  1616.     ADDR addr;
  1617.     int  fp;
  1618.  
  1619.  
  1620.     addr.zone = addr.net = addr.node = addr.point = 0;
  1621.     addr.domain = NULL;
  1622.     fp = open_pkt(&addr,&addr,IS_ADUPE);
  1623.     if(fp != -1) {
  1624.         if(seenby) {
  1625.             seenby--;
  1626.             *seenby = '\r';
  1627.         }
  1628.         if(pathline) {
  1629.             pathline--;
  1630.             *pathline = '\r';
  1631.         }
  1632.         if(newpath && *buff) {
  1633.             newpath[strlen(newpath)] = '\r';
  1634.         }
  1635.         write_pkt_msg(fp,xmsg,NULL,NULL,NULL,buff,area,NULL);
  1636.     }
  1637.     else return -1;
  1638.     close(fp);
  1639.     return 0;
  1640. }
  1641.  
  1642.  
  1643.  
  1644.  
  1645. static int _fastcall is_notforwarded (char *buff,XMSG *xmsg) {
  1646.  
  1647.     ADDR addr;
  1648.     int  fp;
  1649.  
  1650.  
  1651.     addr.zone = addr.net = addr.node = addr.point = 0;
  1652.     addr.domain = NULL;
  1653.     fp = open_pkt(&addr,&addr,IS_NOFORWARD);
  1654.     if(fp != -1) {
  1655.         write_pkt_msg(fp,xmsg,NULL,NULL,NULL,buff,NULL,NULL);
  1656.     }
  1657.     else return -1;
  1658.     close(fp);
  1659.     return 0;
  1660. }
  1661.  
  1662.  
  1663.  
  1664.  
  1665. static int _fastcall open_pkt (ADDR *addr,ADDR *faddr,int which) {
  1666.  
  1667.     int         fp;
  1668.     long        pos;
  1669.     PKTHDR      ph;
  1670.     ADDR        *maddr;
  1671.     static char currout[1027];
  1672.     char        *p;
  1673.  
  1674.  
  1675.     /* Open (create if necessary) a packet for address given.
  1676.        Return a file handle for the packet positioned to eop */
  1677.  
  1678.     if(which == IS_UNKNOWN) {
  1679.         sprintf(buffer,"%s/UNKNOWN.$$$",inbound);
  1680.     }
  1681.     else if(which == IS_INSECURE) {
  1682.         sprintf(buffer,"%s/INSECURE.$$$",inbound);
  1683.     }
  1684.     else if(which == IS_ADUPE) {
  1685.         sprintf(buffer,"%s/AREDUPES.$$$",inbound);
  1686.     }
  1687.     else if(which == IS_NOFORWARD) {
  1688.         sprintf(buffer,"%s/FORWARD.$$$",inbound);
  1689.     }
  1690.     else {
  1691.         if(!control.xbbsos2) {
  1692.             strcpy(currout,outbound);
  1693.             if(addr->domain && *addr->domain && stricmp(myaddr->domain,addr->domain)) {
  1694.                                 p = strrchr(currout,'\\');
  1695.                 if(p) p++;
  1696.                 else p = &currout[strlen(currout)];
  1697.                 strcat(currout,addr->domain);
  1698.             }
  1699.             if(myaddr->zone != addr->zone) {
  1700.                 sprintf(&currout[strlen(currout)],".%03x",addr->zone);
  1701.                 DosMkDir(currout,0L);
  1702.             }
  1703.             sprintf(buffer,"%s/%04x%04x.OUT",currout,addr->net,addr->node);
  1704.         }
  1705.         else {
  1706.             sprintf(buffer,"%s/P.%u.%u.%u.%u.%0.8s",outbound,addr->zone,addr->net,
  1707.                     addr->node,addr->point,addr->domain);
  1708.         }
  1709.     }
  1710.  
  1711.     fp = sopen(buffer,O_RDWR | O_BINARY | O_CREAT,SH_DENYWR,S_IREAD | S_IWRITE);
  1712.     if(fp != -1) {
  1713.         lseek(fp,0L,SEEK_END);
  1714.         if(!tell(fp)) {
  1715.             memset(&ph,0,sizeof(PKTHDR));
  1716.             ph.version = 2;
  1717.             ph.subver = 2;
  1718.             ph.dnode  = addr->node;
  1719.             ph.dnet   = addr->net;
  1720.             ph.dzone  = addr->zone;
  1721.             ph.dpoint = addr->point;
  1722.             if(addr->domain) strncpy(ph.ddomain,addr->domain,8);
  1723.             if(!faddr) maddr = best_guess(addr,myaddr);
  1724.             else maddr = faddr;
  1725.             ph.onode  = maddr->node;
  1726.             ph.onet   = maddr->net;
  1727.             ph.ozone  = maddr->zone;
  1728.             ph.opoint = maddr->point;
  1729.             if(maddr->domain) strncpy(ph.odomain,maddr->domain,8);
  1730.             write(fp,&ph,sizeof(PKTHDR));
  1731.             write(fp,"\0",2);
  1732.         }
  1733.         pos = tell(fp);
  1734.         if(pos) lseek(fp,pos - 2L,SEEK_SET);  /* Position to next msg spot */
  1735.     }
  1736.     return fp;
  1737. }
  1738.  
  1739.  
  1740.  
  1741.  
  1742. static int _fastcall write_pkt_msg (int fp,XMSG *amsg,SB *opth,ADDR *naddr,
  1743.                                     ADDR *maddr,char *text,char *area,
  1744.                                     SB *sb) {
  1745.  
  1746.     char pmsg[192],*p;
  1747.     word x;
  1748.     /* long pos; */
  1749.  
  1750.  
  1751.     /* Write the message given to the end of the file given as a
  1752.        packed msg */
  1753.  
  1754.     memset(pmsg,192,0);
  1755.     *pmsg = 0x02;
  1756.     pmsg[1] = 0x00;
  1757.     memcpy(&pmsg[2],&amsg->orig,2);
  1758.     memcpy(&pmsg[4],&amsg->dest,2);
  1759.     memcpy(&pmsg[6],&amsg->orig_net,2);
  1760.     memcpy(&pmsg[8],&amsg->dest_net,2);
  1761.     memcpy(&pmsg[10],&amsg->attr,2);
  1762.     x = 0;
  1763.     memcpy(&pmsg[12],&x,2);
  1764.     for(x = 0;x < 20;x++) if(!amsg->date[x]) amsg->date[x]=' ';
  1765.     amsg->date[19] = 0;                   /* Goddamn qmail anyway... */
  1766.     memcpy(&pmsg[14],amsg->date,20);    
  1767.     p = &pmsg[34];
  1768.     strcpy(p,amsg->to);
  1769.     x = 34;
  1770.     while(*p){
  1771.         x++;
  1772.         p++;
  1773.     }
  1774.     p++;
  1775.     x++;
  1776.     strcpy(p,amsg->from);
  1777.     while(*p){
  1778.         x++;
  1779.         p++;
  1780.     }
  1781.     x++;
  1782.     p++;
  1783.     strcpy(p,amsg->subj);
  1784.     while(*p){
  1785.         x++;
  1786.         p++;
  1787.     }
  1788.     x++;
  1789.     p++;
  1790.     write(fp,pmsg,x);
  1791.     if(area && *area) {             /* Prepend area tag */
  1792.         write(fp,"AREA: ",6);
  1793.         write(fp,area,strlen(area));
  1794.         write(fp,"\r",1);
  1795.     }
  1796.     if(area && *area && (opth || naddr || maddr))
  1797.       spit_newpath(opth,naddr,maddr,fp);
  1798.     write(fp,text,strlen(text));
  1799.     if(area && *area && sb)
  1800.       spit_seenbys(sb,fp);
  1801.     write(fp,"\0\0",3);
  1802. /*
  1803.     pos = tell(fp);
  1804.     if(pos) lseek(fp,pos - 2L,SEEK_SET);  // Position to next msg spot
  1805. */
  1806.     return 1;
  1807. }
  1808.