home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / soupbox0.zip / SOUPPKT.C < prev    next >
C/C++ Source or Header  |  1998-01-25  |  16KB  |  520 lines

  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <io.h>
  5. #include <fcntl.h>
  6. #include <sys\types.h>
  7. #include <sys\stat.h>
  8. #include <process.h>
  9.  
  10. #define BLKSIZE 1024
  11. #define FALSE 0
  12. #define TRUE (!FALSE)
  13.  
  14. //global error flag for *.pkt write
  15. int err=0;
  16.  
  17. //global variables read from soupbox.cfg for souppkt & pktsoup conversion
  18. char email[40];           //soup area tagname to strip from/add to e-mail
  19. int nb=0;                 //# of binaries hierarchies & special handler progs
  20. char bin[10][80];         //root name of binary groups to send to decode.cmd
  21. char decoder[10][40];     //names of programs to store or decode binaries
  22. int nd=0;                 //# of defined ftn destinations/domain names
  23. char domain[40][80];      //domain to put in "from:user@domain" for pkt2soup.c
  24. struct FADDR
  25.  {short zone,net,node,point;}
  26.  org, dest[40];            //fido-style *.pkt source & destination address
  27. unsigned long split=12345; //point to split long inbound soup->ftn messages
  28. char reply[80],tz[40];     //path to outbound ftn packet and name of timezone
  29. int ne=0;                  //number of e-mail attach downlinks
  30. char encoder[10][40],      //program to encode e-mail attach packets
  31.      eheader[10][40],      //header to prepend to encoded e-mail
  32.      epacket[10][60];      //files to send as encoded e-mail
  33.  
  34. int nr=0;                  //number of user replace/replaceall/alias addresses
  35. char addr0[40][50],
  36.      addr1[40][50],
  37.      reptype[40];
  38. #define ALIAS 1
  39. #define REPLACE 2
  40. #define REPLACEALL 3
  41.  
  42. //call write() and remember error codes
  43. int wwrite(int file,char *blk,int len)
  44. {
  45.  int rc;
  46.  rc=write(file,blk,len);
  47.  if (rc<0)
  48.    err=rc;
  49.  return rc;
  50. }
  51.  
  52. //read soupbox.cfg configuration file - note some of these values are unused
  53. //store result in global variables - return TRUE if successful, else FALSE
  54. int initialize(char *file)
  55. {
  56.  FILE *in;
  57.  static char line[128],tag[40],val1[80],val2[80],val3[80];  //one line of soupbox.cfg file
  58.  
  59.  in=fopen(file,"r");
  60.  if (!in)
  61.   {printf("error - unable to open soupbox.cfg");
  62.    return FALSE;}
  63.  
  64.  while (!feof(in))
  65.    {
  66.     line[0]=tag[0]=val1[0]=val2[0]=val3[0]=0;
  67.     fgets(line,sizeof(line),in);
  68.     sscanf(line,"%s %s %s %s",tag,val1,val2,val3);
  69.     if (!stricmp(tag,"Origin"))
  70.         sscanf(val1,"%d:%d/%d.%d",&org.zone,&org.net,&org.node,&org.point);
  71.     if (!stricmp(tag,"Domain"))
  72.      {
  73.         sscanf(val1,"%d:%d/%d.%d",&dest[nd].zone,&dest[nd].net,&dest[nd].node,&dest[nd].point);
  74.         strcpy(domain[nd],val2);
  75.         nd++;
  76.       }
  77.     if (!stricmp(tag,"e-mail"))
  78.          strcpy(email,val1);
  79.     if (!stricmp(tag,"Split"))
  80.          sscanf(val1,"%ld",&split);     //#bytes at which to split long msgs
  81.     if (!stricmp(tag,"Encode"))
  82.      {
  83.         strcpy(encoder[ne],val1);       //name of encoder program
  84.         strcpy(eheader[ne],val2);       //header for e-mail attach
  85.         strcpy(epacket[ne],val3);       //packets to send via e-mail attach
  86.         ne++;
  87.       }
  88.     if (!stricmp(tag,"Decode"))
  89.      {
  90.         strcpy(decoder[nb],val1);
  91.         strcpy(bin[nb],val2);
  92.         nb++;
  93.       }
  94.     if (!stricmp(tag,"Alias"))
  95.      {
  96.         strcpy(addr0[nr],val1);       //address on BBS for this user
  97.         strcpy(addr1[nr],val2);       //address to use on internet
  98.         reptype[nr]=ALIAS;
  99.         nr++;
  100.       }
  101.     if (!stricmp(tag,"Replace"))
  102.      {
  103.         strcpy(addr0[nr],val1);       //address on BBS for this user
  104.         strcpy(addr1[nr],val2);       //address to use on internet
  105.         reptype[nr]=REPLACE;
  106.         nr++;
  107.       }
  108.     if (!stricmp(tag,"ReplaceAll"))
  109.      {
  110.         strcpy(addr0[nr],val1);       //address on BBS for this user
  111.         strcpy(addr1[nr],val2);       //address to use on internet
  112.         reptype[nr]=REPLACEALL;
  113.         nr++;
  114.       }
  115.     if (!stricmp(tag,"Reply"))
  116.         strcpy(reply,val1);
  117.     if (!stricmp(tag,"TimeZone"))
  118.          strcpy(tz,val1);
  119.    }
  120.  fclose(in);
  121.  
  122.  if (!nd)
  123.  {
  124.    printf("error - no fido destination address & domain name in config file\n");
  125.    return FALSE;
  126.  }
  127.  
  128.  //TO DO: check config. values for validity
  129.  return TRUE;
  130. }
  131.  
  132. //souppkt.c-specific section
  133.  
  134. //this writes a fts-0048 (type 2+) fido packet header using org, dest[0] as
  135. //node number, no packet passwords
  136.  
  137. int pkthdr(int file)
  138. {
  139.   int i;
  140.   //org/dest[0] node
  141.   write(file,&org.node,2);
  142.   write(file,&dest[0].node,2);
  143.   //use dummy values for date/time - Aug 1997
  144.   write(file,"\xcd\x07\x07\x00\x0f\x00\x00\x00\x00\x00\x00\x00",12);
  145.   //bps=0, pkt type=2
  146.   write(file,"\x00\x00\x02\x00",4);
  147.   //org/dest[0] net
  148.   i=org.net;
  149. //if (org.point) i=-1;        //originating net=-1 if point
  150.   write(file,&i,2);
  151.   write(file,&dest[0].net,2);
  152.   //prod code=fido
  153.   write(file,"\x00\x01",2);
  154.   //no packet password
  155.   write(file,"\x00\x00\x00\x00\x00\x00\x00\x00",8);
  156.   //org/dest[0] zone
  157.   write(file,&org.zone,2);
  158.   write(file,&dest[0].zone,2);
  159.   //remainder is type2+ hdr data for ftsc48 4D/point support
  160.   write(file,&org.net,2);       //aux net
  161.   i=256;write(file,&i,2);       //2nd capability word
  162.   i=176;write(file,&i,2);       //product/revision code
  163.   i=1;write(file,&i,2);         //capability word
  164.   //org/dest[0] zone
  165.   write(file,&org.zone,2);
  166.   write(file,&dest[0].zone,2);
  167.   //org/dest[0] point
  168.   write(file,&org.point,2);
  169.   write(file,&dest[0].point,2);
  170.   write(file,"XPKT",4);
  171. }
  172.  
  173. //tofield() - this changes Internet "to:" field to BBS username & domain #
  174. unsigned tofield(char *to,char *s,int maxlen)
  175. {
  176.     int i,st=0,end=0;
  177.     int dom;               //pointer to BBS in list of our domains
  178.  
  179.     //extract first user@domain address from Internet to: field
  180.     //remove trailing (screen name) or > from address
  181.     while (s[end] && s[end]!='(' && s[end]!='>') end++;
  182.     //remove scrname if scrname <addr@domain> format
  183.     while (s[st] && s[st]!='<') st++;
  184.     if (s[st]==0)
  185.     {
  186.       st=0;               //remove leading punctuation
  187.       while (s[st] && s[st]<'0') st++;
  188.     }
  189.     else st++;           //skip over < in address
  190.     strcpy(to,s+st);
  191.     to[end-st]=0;
  192.  
  193.     //replace forwarded outside Internet addresses with user@BBS addresses
  194.     for (i=0;i<nr;i++)
  195.       if (!stricmp(to,addr1[i]))
  196.         strcpy(to,addr0[i]);
  197.  
  198.     //remove @domain for our addresses on inbound mail
  199.     {
  200.      int j,dd=0;
  201.      dom=0;
  202.      while (to[dd] && to[dd]!='@') dd++;     //get domain name
  203.      if (to[dd]) dd++;
  204.      if (to[dd])
  205.       {
  206.        for (i=0;i<nd;i++)
  207.        {
  208.          if (!stricmp(domain[i],to+dd))     //if inbound to one of ours
  209.            {
  210.             dom=i;                          //keep index into BBS domain list
  211.             to[dd-1]=0;                     //remove domain name
  212.             for (j=0;j<=dd-1;j++)
  213.               if (to[j]=='.') to[j]=' ';    //change .'s to spaces
  214.             break;
  215.            }
  216.         }
  217.       }
  218.     }
  219.     to[maxlen]=0;
  220.     return dom;                              //return index to our list of BBS domains
  221. }
  222.  
  223. //this reads ASCII headers from inbound soup to get date/from/x-to/subj
  224. unsigned gethdr(int msg,char date[],char from[],char to[],char subj[],char orgn[])
  225. {
  226.  unsigned char s[255],p;
  227.  unsigned long posn;
  228.  unsigned dom=0;              //domain # as determined from to: field of e-mail
  229.  
  230.  //remember original position
  231.  posn=lseek(msg,0,SEEK_CUR);
  232.  
  233.  //read headers until empty line found
  234.  do
  235.  {
  236.    s[0]='\n';
  237.  
  238.    //read a line of input
  239.    read(msg,s,1);
  240.    for (p=1;p<255 && s[p-1] != '\n';p++)
  241.      read(msg,s+p,1);
  242.    s[p]=0;
  243.    if (p>1)
  244.      s[p-1]=0;
  245.  
  246.    //keep date/from/x-to/subject if found
  247.    //delete any leading spaces or unwanted info
  248.    if (!memcmp(s,"Date:",5))
  249.      {
  250.        int p1;
  251.        p=5;
  252.        while (s[p] && (s[p]<'0' || s[p]>'9')) p++;
  253.        //strip 19.. from beginning of 19xx year (not y2k compliant)
  254.        if ((!memcmp(s+p+6," 19",3)) || (!memcmp(s+p+6," 20",3)))
  255.           for (p1=p+7;s[p1];p1++) s[p1]=s[p1+2];
  256.        if ((!memcmp(s+p+5," 19",3)) || (!memcmp(s+p+5," 20",3)))
  257.           for (p1=p+6;s[p1];p1++) s[p1]=s[p1+2];
  258.        s[p+19]=0;
  259.        strcpy(date,s+p);
  260.      }
  261.    //strip screen names and leading spaces from From:
  262.    if (!memcmp(s,"From:",5))
  263.      {
  264.         p=5;                 //remove trailing (screen name) or > from address
  265.         while (s[p] && s[p]!='(' && s[p]!='>') p++;
  266.         s[p]=0;
  267.         p=5;                 //remove scrname if scrname <addr@domain> format
  268.         while (s[p] && s[p]!='<') p++;
  269.         if (s[p]==0)
  270.         {
  271.           p=5;               //remove leading punctuation
  272.           while (s[p] && s[p]<'0') p++;
  273.         }
  274.         else p++;           //skip over < in address
  275.         s[p+35]=0;
  276.         strcpy(from,s+p);
  277.       }
  278.    //strip leading spaces from x-to and subject lines
  279.    if (!memcmp(s,"X-To:",5))
  280.       dom=tofield(to,s+5,35);
  281.    if (!memcmp(s,"To:",3))
  282.       dom=tofield(to,s+3,35);
  283.    if (!memcmp(s,"X-Ftn-To:",9))
  284.       dom=tofield(to,s+9,35);
  285.    if (!memcmp(s,"Subject:",8))
  286.      {p=8;
  287.       while (s[p] && s[p]<'0') p++;
  288.       s[71+p]=0;strcpy(subj,s+p);}
  289.    if (!memcmp(s,"Organization:",13))
  290.      {p=13;
  291.       while (s[p] && s[p]<'0') p++;
  292.       s[56+p]=0;strcpy(orgn,s+p);}
  293.  }
  294.  //quit on empty line or eof and restore original position
  295.  while (s[0]!='\n');
  296.  lseek(msg,posn,SEEK_SET);
  297.  return dom;
  298. }
  299.  
  300. //write message headers for one fido-style message
  301. //this may be called more than once if a message is split due to length
  302. void writehdr(int file,char *date,char *from,char *to,char *subj,char *area,unsigned dom,unsigned part)
  303. {
  304.   //write message header
  305.   write(file,"\x02\x00",2);
  306.   write(file,&org.node,2);
  307.   write(file,&dest[dom].node,2);
  308.   write(file,&org.net,2);
  309.   write(file,&dest[dom].net,2);
  310.  
  311.   //attributes and cost
  312.   if (!!stricmp(area,email))
  313.     write(file,"\x00\x00\x00\x00",4); //public (echo) message
  314.   else
  315.     write(file,"\x01\x00\x00\x00",4); //private (netmail)
  316.  
  317.   //write date/to/from/subj
  318.   write(file,date,strlen(date)+1);
  319.   write(file,to,strlen(to)+1);
  320.   write(file,from,strlen(from)+1);
  321.   if (!part)
  322.      write(file,subj,strlen(subj)+1);
  323.   else
  324.     {
  325.      char s[80];             //insert segment # if a split/long msg
  326.      s[0]='0'+part/10;
  327.      s[1]='0'+part%10;
  328.      s[2]=':';
  329.      strcpy(s+3,subj);
  330.      s[72]=0;
  331.      write(file,s,strlen(s)+1);
  332.     }
  333.  
  334.   //write area tag
  335.   if (!!stricmp(area,email))
  336.   {
  337.     write(file,"AREA:",5);
  338.     write(file,area,strlen(area));
  339.     write(file,"\r",1);
  340.   }
  341.   //write FMPT/TOPT/INTL netmail kludges if needed in netmail
  342.   else
  343.   {
  344.     char s[80];
  345.     sprintf(s,"\001FMPT %d\r",org.point);
  346.     if (org.point)
  347.       write(file,s,strlen(s));
  348.     sprintf(s,"\001TOPT %d\r",dest[dom].point);
  349.     if (dest[dom].point)
  350.       write(file,s,strlen(s));
  351.     sprintf(s,"\001INTL %d:%d/%d %d:%d/%d\r", org.zone, org.net, org.node,
  352.             dest[dom].zone, dest[dom].net, dest[dom].node);
  353.     if (org.zone!=1 || dest[dom].zone!=1)
  354.       write(file,s,strlen(s));
  355.   }
  356. }
  357.  
  358. //write ftn message footer - origin, end markers
  359. void writeftr(int file,char *area,char *orgn)
  360. {
  361.   //write fido origin line and control info
  362.   if (!!stricmp(area,email))
  363.   {
  364.      char addr[40];
  365.  
  366.      //write tearline and origin line
  367.      write(file,"\r\r---\r * Origin: ",17);
  368.      write(file,orgn,strlen(orgn));
  369.      sprintf(addr," (%d:%d/%d.%d)\r",org.zone,org.net,org.node,org.point);
  370.      write(file,addr,strlen(addr));
  371.  
  372.      //write echomail SEEN-BY and PATH:
  373.      sprintf(addr,"SEEN-BY: %d/%d\r",org.net,org.node);
  374.      write(file,addr,strlen(addr));
  375.      sprintf(addr,"\001PATH: %d/%d\r",org.net,org.node);
  376.      write(file,addr,strlen(addr));
  377.   }
  378.   //write end marker
  379.   write(file,"",1);
  380. }
  381.  
  382. //convert one individual message to include in existing *.pkt file
  383. //assume packet header has already been written
  384. int cvtm2pkt(int file,int msg,char *area)
  385. {
  386.   unsigned i,j;
  387.   unsigned char c,mlen[4];
  388.   unsigned long len,pos,segpos;
  389.   static unsigned char date[20],from[40],to[40],subj[80],orgn[80];
  390.   int rc;
  391.   unsigned dom;         //index into BBS domain list for inbound e-mail
  392.   unsigned part=0;      //segment # if splitting long message
  393.  
  394.   rc=read(msg,&mlen,4);     //get length of message body
  395.   if (rc<=0)
  396.     return 0;
  397.   len=0;
  398.   for (i=0;i<4;i++)
  399.     len= (len << 8L)+(unsigned long) mlen[i];
  400.  
  401.   //defaults-gethdr will replace these with actual message info if present
  402.   strcpy(date,"01 Jan 97  00:00:00");
  403.   strcpy(from,area);
  404.   strcpy(to,"All");
  405.   strcpy(subj,"stuff");
  406.   strcpy(orgn,"none");
  407.  
  408.   //get header info from message
  409.   dom=gethdr(msg,date,from,to,subj,orgn);
  410.   if (!!stricmp(area,email))
  411.     dom=0;                      //send all news to first (default) BBS domain
  412.  
  413.   if (len>split) part=1;
  414.   writehdr(file,date,from,to,subj,area,dom,part); //write header for one ftn message
  415.  
  416.   //copy message body
  417.   rc=1;
  418.   segpos=0;                  //position in this segment of split/long message
  419.  
  420.   for (pos=0;pos<len && rc>0;)
  421.   {
  422.     unsigned long blksize=len-pos;
  423.     unsigned char c[BLKSIZE];
  424.     int i;
  425.     if (blksize>BLKSIZE)
  426.        blksize=BLKSIZE;
  427.     if (segpos+blksize > split)
  428.        blksize=split-segpos;
  429.     rc=read(msg,c,(unsigned) blksize);
  430.     for (i=0;i<blksize;i++)
  431.       if (c[i]==10) c[i]=13; //convert lf to cr
  432.     write(file,c,(unsigned) blksize);
  433.     pos+=blksize;
  434.     segpos+=blksize;
  435.     if (segpos>=split && pos<len)    //if too long, insert a ftn split here
  436.     {
  437.       //copy remainder of current line
  438.       char c=0;
  439.       while (pos<len && c!=13 && rc>0)
  440.         {
  441.          rc=read(msg,&c,1);
  442.          if (c==10) c=13; //convert lf to cr
  443.          write(file,&c,1);
  444.          pos++;
  445.         }
  446.       //create split (msg footer then header of next segment)
  447.       //TO DO: indicate split in ftn kludge lines
  448.       writeftr(file,area,orgn);
  449.       part++;                    //increment msg part# in subject line
  450.       writehdr(file,date,from,to,subj,area,dom,part);
  451.       segpos=0;
  452.     }
  453.   }
  454.  
  455.   writeftr(file,area,orgn);         //write ftn footer - origin: and end markers
  456.   return 1;
  457. }
  458.  
  459. void main(void)
  460. {
  461.  static unsigned char fname[40],area[40],type[20];
  462.  int i;
  463.  FILE *areas;
  464.  
  465.  err=0;
  466.  if (!initialize("soupbox.cfg"))
  467.    return;
  468.  
  469.  areas=fopen("areas","rb");
  470.  if (!areas)
  471.    return;
  472.  
  473.  while (!feof(areas))
  474.  {
  475.   int in,out;
  476.   static char pkt[40];
  477.   fname[0]=area[0]=type[0]=0;
  478.   if (fscanf(areas,"%s\t%s\t%s\n",fname,area,type)>0)
  479.   {
  480.      printf("file %s area %s type %s",fname,area,type);
  481.      strcpy(pkt,fname);
  482.      strcat(fname,".msg");
  483.      strcat(pkt,".pkt");
  484.      for (i=0;i<nb;i++)
  485.       if (!memicmp(area,bin[i],strlen(bin[i])))  //if binary group, give msg to decoder
  486.       {
  487.        char s[80];
  488.        sprintf(s,"%s %s %s",decoder[i],fname,area);
  489.        system(s);
  490.       }
  491.      in=open(fname,O_RDONLY|O_BINARY);    //if msg still exists, convert to .pkt
  492.      //check to see if output .pkt file already exists
  493.      out=open(pkt,O_RDONLY|O_BINARY);
  494.      if (out>0)
  495.      {
  496.        err=1;close(out);
  497.        printf("\nerror creating %s - file already exists\n",pkt);
  498.        exit(1);
  499.      }
  500.      else if (in>0)
  501.      {
  502.         out=open(pkt,O_WRONLY|O_BINARY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE);
  503.         pkthdr(out);
  504.         while (cvtm2pkt(out,in,area)) printf(".");
  505.         printf("\n");
  506.         write(out,"\0",2);
  507.         close(out);
  508.      }
  509.      close(in);
  510.      if (!err)
  511.        remove(fname);
  512.   }
  513.  }
  514.  fclose(areas);
  515.  if (!err)
  516.    remove("areas");
  517.  else
  518.    printf("\ndisk write error during soup/pkt conversion\n");
  519. }
  520.