home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / XGRP_000.SZH / EMAILOUT.C < prev    next >
C/C++ Source or Header  |  1991-08-23  |  15KB  |  517 lines

  1. /* echomail scanner */
  2.  
  3. #include <limits.h>
  4. #include "xgroup.h"
  5.  
  6. #define MAXKLUDGE 256
  7.  
  8. #define SETSCANNED(x) (x.m_attr |= MSGSCANNED)
  9. #define SETSENT(x) (x.attr |= MSGSENT)
  10. #define RESETSENT(x) (x.attr &= (~MSGSENT))
  11. #define SETDELETED(x) (x.m_attr |= MSGDELETED)
  12.  
  13. /* function declarations specific to this module */
  14.  
  15. static int  _fastcall open_pkt (ADDR *addr);
  16. static word _fastcall find_last_scanned (int dataptr);
  17. static int  _fastcall write_pkt_msg (int fp,XMSG *amsg,char *npth,
  18.                                      char *text,char *area);
  19. static void _fastcall report(void);
  20. static void _fastcall do_export(ECHOREC *einfo,word startat,int dataptr,
  21.                                 int textptr);
  22.  
  23. /* external var references */
  24.  
  25. extern GROUP    *group;
  26. extern CONTROLS control;
  27. extern ADDR     *myaddr;
  28. extern ECHOREC  *echos;
  29. extern char     *groupin;
  30. extern char     *groupout;
  31. extern char     *grouphold;
  32. extern char     *msgdir;
  33. extern char     *archive;
  34. extern char     *unarchive;
  35. extern char     *outbound;
  36. extern char     *inbound;
  37. extern word     packsize;
  38. extern char     buffer[1024];
  39. extern word     netarea;
  40. extern DUPES    *dupes;
  41. extern word     nextdupe,maxdupes;
  42. extern char     founddupes;
  43.  
  44.  
  45.  
  46.  
  47. void _fastcall echo_export_mail (void) {
  48.  
  49.     word        y;
  50.     ECHOREC     *currecho;
  51.     int         dataptr,textptr;
  52.     struct stat st;
  53.  
  54.  
  55.     currecho = echos;
  56.     while(currecho) {
  57.         if(!currecho->addr || !currecho->areano) {    /* pass-thru or local-only */
  58.             currecho = currecho->next;
  59.             continue;
  60.         }
  61.         printf("\nScanning echo area \"%s\"...",currecho->tag);
  62.         sprintf(buffer,"%s/XDATA.%03x",msgdir,currecho->areano);
  63.         if(stat(buffer,&st)) st.st_size = 0L;
  64.         if(!st.st_size) {
  65.             printf("no msgs\n\x1b[K");
  66.             currecho = currecho->next;
  67.             continue;
  68.         }
  69.         else printf("%u msg%s\n\x1b[K",
  70.                     (word)(st.st_size / (long)sizeof(XMSG)),
  71.                     &"s"[((word)(st.st_size / (long)sizeof(XMSG)) == 1)]);
  72.         dataptr = sopen(buffer,O_RDWR | O_BINARY,SH_DENYNO);
  73.         if(dataptr == -1) {
  74.             printf("\nCouldn't open data file %s\n",buffer);
  75.             currecho = currecho->next;
  76.             continue;
  77.         }
  78.         sprintf(buffer,"%s/XTEXT.%03x",msgdir,currecho->areano);
  79.         textptr = sopen(buffer,O_RDWR | O_BINARY,SH_DENYNO);
  80.         if(textptr == -1) {
  81.             close(dataptr);
  82.             printf("\nCouldn't open text file %s\n",buffer);
  83.             currecho = currecho->next;
  84.             continue;
  85.         }
  86.         y = find_last_scanned(dataptr);
  87.         do_export(currecho,y,dataptr,textptr);
  88.         close(textptr);
  89.         close(dataptr);
  90.  
  91.         currecho = currecho->next;
  92.     }
  93.  
  94.     report();
  95. }
  96.  
  97.  
  98.  
  99. void _fastcall report (void) {
  100.  
  101.     ECHOREC *einfo = echos;
  102.     long  totalmsgs = 0L;
  103.  
  104.  
  105.     printf("\n");
  106.  
  107.     while(einfo) {
  108.         if(einfo->exported) {
  109.             logf("Exported %u msg%s from area #%u \"%s\"",einfo->exported,
  110.                  &"s"[(einfo->exported == 1)],einfo->areano,einfo->tag);
  111.             totalmsgs += (long)einfo->exported;
  112.         }
  113.         einfo = einfo->next;
  114.     }
  115.     if(totalmsgs) logf("Total msgs exported: %lu",totalmsgs);
  116. }
  117.  
  118.  
  119.  
  120. static void _fastcall do_export (ECHOREC *einfo,word startat,int dataptr,
  121.                                  int textptr) {
  122.  
  123.     word          x,tries,test;
  124.     word          nummsgs;
  125.     long          pos,msgidcrc,serialno;
  126.     int           fp;
  127.     char          *text = NULL,npthbuf[90],*p,*pp;
  128.     XMSG          xmsg;
  129.     ADDR          *addr,*maddr;
  130.     SB            *s;
  131.  
  132.  
  133.     if(!control.nodupes) load_dupes(einfo->areano);
  134.  
  135.     tries = 0;
  136.     while(tries < 50) {
  137.         if(lseek(dataptr,0L,SEEK_END) != -1L) break;
  138.         DosSleep(100L);
  139.         tries++;
  140.     }
  141.     if(tries >= 50) {
  142.         printf("\nLocking conflict; aborting...(#4)\n");
  143.         my_free(dupes);
  144.         return;
  145.     }
  146.  
  147.     nummsgs = (word)(tell(dataptr) / (long)sizeof(XMSG));
  148.     if(startat) startat--;
  149.     for(x = startat;x < nummsgs;x++) {
  150.  
  151.         tries = 0;
  152.         while(tries < 50) {
  153.             if(lseek(dataptr,(long)x * (long)sizeof(XMSG),SEEK_SET) != -1L) break;
  154.             DosSleep(100L);
  155.             tries++;
  156.         }
  157.         if(tries >= 50) {
  158.             printf("\nLocking conflict; aborting...(#5)\n");
  159.             my_free(dupes);
  160.             return;
  161.         }
  162.  
  163.         pos = tell(dataptr);
  164.         tries = 0;
  165.         while(tries < 50) {
  166.             if((size_t)read(dataptr,&xmsg,sizeof(XMSG)) == sizeof(XMSG)) break;
  167.             DosSleep(100L);
  168.             tries++;
  169.             lseek(dataptr,pos,SEEK_SET);
  170.         }
  171.         if(tries >= 50) {
  172.             printf("\nLocking conflict; aborting...(#6)\n");
  173.             return;
  174.         }
  175.  
  176.         if(xmsg.m_attr & MSGSCANNED) continue;
  177.         if(xmsg.m_attr & MSGDELETED) goto ExportDone;
  178.         if(!(xmsg.m_attr & MSGECHO)) goto ExportDone;
  179.         if(!(xmsg.attr & MSGLOCAL)) goto ExportDone;
  180.         if(xmsg.attr & MSGORPHAN) goto ExportDone;
  181.  
  182.         /* Got one to export */
  183.  
  184.         RESETSENT(xmsg);   /* Reset sent bit--what the hell, be nice */
  185.  
  186.         tries = 0;
  187.         while(tries < 50) {
  188.             if(lseek(textptr,xmsg.start,SEEK_SET) != -1L) break;
  189.             DosSleep(100L);
  190.             tries++;
  191.         }
  192.         if(tries >= 50) {
  193.             printf("\nLocking conflict; aborting...(#7)\n");
  194.             my_free(dupes);
  195.             return;
  196.         }
  197.  
  198.         text = (char *)malloc(xmsg.length + 2);
  199.         if(!text) continue;
  200.  
  201.         tries = 0;
  202.         while(tries < 50) {
  203.             *text = 0;
  204.             test = (word)read(textptr,text,xmsg.length + 1);
  205.             if(test != 65535U) {
  206.                 if(test >= (xmsg.length - 1)) break;
  207.             }
  208.             DosSleep(100L);
  209.             tries++;
  210.             lseek(textptr,xmsg.start,SEEK_SET);
  211.         }
  212.         if(tries >= 50) {
  213.             printf("\nLocking conflict; aborting...(#9)\n");
  214.             return;
  215.         }
  216.  
  217.         if(!*text){
  218.             my_free(text);
  219.             text = NULL;
  220.             continue;
  221.         }
  222.  
  223.         if(xmsg.m_attr & MSGPACKED) {
  224.             if(unpack_msg(&text) == NULL) {
  225.                 my_free(text);
  226.                 text = NULL;
  227.                 continue;
  228.             }
  229.         }
  230.  
  231.         addr = einfo->addr;
  232.         if(addr) {
  233.             einfo->exported++;
  234.             maddr = best_guess(addr,myaddr);
  235.  
  236.             /* construct new path entry */
  237.  
  238.             if(maddr->point) {
  239.                 sprintf(npthbuf,"\01NPTH: %s#%u:%u/%u.%u\r",maddr->domain,
  240.                         maddr->zone,maddr->net,maddr->node,maddr->point);
  241.             }
  242.             else {
  243.                 sprintf(npthbuf,"\01NPTH: %s#%u:%u/%u\r",maddr->domain,
  244.                         maddr->zone,maddr->net,maddr->node);
  245.             }
  246.         }
  247.  
  248.         while(addr) {
  249.             fp = open_pkt(addr);
  250.             if(fp == -1) {
  251.                 addr = addr->next;
  252.                 if(addr) continue;
  253.                 my_free(text);
  254.                 text = NULL;
  255.                 break;
  256.             }
  257.  
  258.             xmsg.d_zone = addr->zone;
  259.             xmsg.dest_net = addr->net;
  260.             xmsg.dest = addr->node;
  261.             xmsg.d_point = addr->point;
  262.  
  263.             printf("#%u (#%u)\r",
  264.                    x+1,einfo->exported);
  265.  
  266.             text[xmsg.length] = 0;
  267.             text[xmsg.length-1] = 0;
  268.  
  269.             write_pkt_msg(fp,&xmsg,npthbuf,text,einfo->tag);
  270.  
  271.             /* add tiny seen-bys */
  272.  
  273.             s = make_tinysbs(einfo,NULL);
  274.             if(s) {
  275.                 lseek(fp,(tell(fp) - 1L),SEEK_SET);
  276.                 spit_seenbys(s,fp);
  277.                 write(fp,"\0\0",3);
  278.                 lseek(fp,(tell(fp) - 2L),SEEK_SET);  /* Ready for another msg */
  279.                 my_free(s);
  280.             }
  281.  
  282.             close(fp);
  283.             addr = addr->next;
  284.         }
  285.  
  286.         if(!control.nodupes && dupes) {
  287.             if(!strcmp(text,"\01MSGID: ")) {
  288.                 strncpy(npthbuf,&text[8],89);
  289.                 npthbuf[89] = 0;
  290.                 p = strchr(npthbuf,'\r');
  291.                 if(p) *p = 0;
  292.                 lstrip(npthbuf);
  293.                 rstrip(npthbuf);
  294.                 p = strchr(npthbuf,' ');
  295.                 if(p) {
  296.                     *p = 0;
  297.                     msgidcrc = crc32str(npthbuf,1);
  298.                     *p = ' ';
  299.                     p++;
  300.                     pp = p;
  301.                     serialno = strtol(p,&pp,16);
  302.                     if((serialno == LONG_MIN || serialno == LONG_MAX) &&
  303.                       errno == ERANGE) serialno = 0L;
  304.                     if(msgidcrc && serialno) {
  305.                         dupes[nextdupe].msgidcrc = msgidcrc;
  306.                         dupes[nextdupe].serialno = serialno;
  307.                         nextdupe++;
  308.                         founddupes = 1;
  309.                         if(nextdupe >= maxdupes) nextdupe = 0;
  310.                     }
  311.                 }
  312.             }
  313.         }
  314.  
  315.         my_free(text);
  316.         text = NULL;
  317.         SETSENT(xmsg);      /* Set sent bit */
  318.         if(xmsg.attr & MSGKILL)
  319.           SETDELETED(xmsg); /* delete if so marked*/
  320.  
  321. ExportDone:
  322.  
  323.         SETSCANNED(xmsg);   /* Rewrite header w/ echos-scanned bit set */
  324.         tries = 0;
  325.         while(tries < 50) {
  326.             if(lseek(dataptr,pos,SEEK_SET) != -1L) break;
  327.             DosSleep(100L);
  328.             tries++;
  329.         }
  330.         if(tries < 50) {
  331.             locking(dataptr,LK_LOCK,(long)sizeof(XMSG));
  332.             write(dataptr,&xmsg,sizeof(XMSG));
  333.             lseek(dataptr,pos,SEEK_SET);
  334.             locking(dataptr,LK_UNLCK,(long)sizeof(XMSG));
  335.         }
  336.     }
  337.  
  338.     if(dupes) free_dupes();
  339. }
  340.  
  341.  
  342.  
  343. static int _fastcall open_pkt (ADDR *addr) {
  344.  
  345.     int         fp;
  346.     long        pos;
  347.     PKTHDR      ph;
  348.     ADDR        *maddr;
  349.     static char currout[1027];
  350.     char        *p;
  351.  
  352.  
  353.     /* Open (create if necessary) a packet for address given.
  354.        Return a file handle for the packet positioned to eop */
  355.  
  356.     if(!control.xbbsos2) {
  357.         strcpy(currout,outbound);
  358.         if(addr->domain && *addr->domain && stricmp(myaddr->domain,addr->domain)) {
  359.                         p = strrchr(currout,'\\');
  360.             if(p) p++;
  361.             else p = &currout[strlen(currout)];
  362.             strcat(currout,addr->domain);
  363.         }
  364.         if(myaddr->zone != addr->zone) {
  365.              sprintf(&currout[strlen(currout)],".%03x",addr->zone);
  366.              DosMkDir(currout,0L);
  367.         }
  368.         sprintf(buffer,"%s/%04x%04x.OUT",currout,addr->net,addr->node);
  369.     }
  370.     else {
  371.         sprintf(buffer,"%s/P.%u.%u.%u.%u.%0.8s",outbound,addr->zone,addr->net,
  372.                 addr->node,addr->point,addr->domain);
  373.     }
  374.  
  375.     fp = sopen(buffer,O_RDWR | O_BINARY | O_CREAT,SH_DENYWR,S_IREAD | S_IWRITE);
  376.     if(fp != -1) {
  377.         lseek(fp,0L,SEEK_END);
  378.         if(!tell(fp)) {
  379.             memset(&ph,0,sizeof(PKTHDR));
  380.             ph.version = 2;
  381.             ph.subver = 2;
  382.             ph.dnode  = addr->node;
  383.             ph.dnet   = addr->net;
  384.             ph.dzone  = addr->zone;
  385.             ph.dpoint = addr->point;
  386.             strncpy(ph.ddomain,addr->domain,8);
  387.             maddr = best_guess(addr,myaddr);
  388.             ph.onode  = maddr->node;
  389.             ph.onet   = maddr->net;
  390.             ph.ozone  = maddr->zone;
  391.             ph.opoint = maddr->point;
  392.             strncpy(ph.odomain,maddr->domain,8);
  393.             write(fp,&ph,sizeof(PKTHDR));
  394.             write(fp,"\0",2);
  395.         }
  396.         pos = tell(fp);
  397.         if(pos) lseek(fp,pos - 2L,SEEK_SET);  /* Position to next msg spot */
  398.     }
  399.     return fp;
  400. }
  401.  
  402.  
  403.  
  404.  
  405. static int _fastcall write_pkt_msg (int fp,XMSG *amsg,char *npth,
  406.                                     char *text,char *area) {
  407.  
  408.     char pmsg[192],*p;
  409.     word x;
  410.  
  411.  
  412.     /* Write the message given to the end of the file given as a
  413.        packed msg */
  414.  
  415.     memset(pmsg,192,0);
  416.     *pmsg = 0x02;
  417.     pmsg[1] = 0x00;
  418.     memcpy(&pmsg[2],&amsg->orig,2);
  419.     memcpy(&pmsg[4],&amsg->dest,2);
  420.     memcpy(&pmsg[6],&amsg->orig_net,2);
  421.     memcpy(&pmsg[8],&amsg->dest_net,2);
  422.     memcpy(&pmsg[10],&amsg->attr,2);
  423.     x = 0;
  424.     memcpy(&pmsg[12],&x,2);
  425.     for(x = 0;x < 20;x++) if(!amsg->date[x]) amsg->date[x] = 'Q';
  426.     amsg->date[19] = 0;                   /* damn qmail anyway... */
  427.     memcpy(&pmsg[14],amsg->date,20);    
  428.     p = &pmsg[34];
  429.     strcpy(p,amsg->to);
  430.     x = 34;
  431.     while(*p){
  432.         x++;
  433.         p++;
  434.     }
  435.     p++;
  436.     x++;
  437.     strcpy(p,amsg->from);
  438.     while(*p){
  439.         x++;
  440.         p++;
  441.     }
  442.     x++;
  443.     p++;
  444.     strcpy(p,amsg->subj);
  445.     while(*p){
  446.         x++;
  447.         p++;
  448.     }
  449.     x++;
  450.     p++;
  451.     write(fp,pmsg,x);
  452.     if(area && *area) {             /* Prepend area tag */
  453.         write(fp,"AREA: ",6);
  454.         write(fp,area,strlen(area));
  455.         write(fp,"\r",1);
  456.     }
  457.     write(fp,npth,strlen(npth));
  458.     write(fp,text,strlen(text));
  459.     write(fp,"\0\0",3);
  460.     lseek(fp,(tell(fp) - 2L),SEEK_SET);  /* Ready for another msg */
  461.     return 1;
  462. }
  463.  
  464.  
  465.  
  466. static word _fastcall find_last_scanned (int dataptr) { /* Speed up someday... */
  467.  
  468.     long          pos;
  469.     register word x;
  470.     int           tries;
  471.     XMSG          xmsg;
  472.  
  473.  
  474.  
  475.     tries = 0;
  476.     while(tries < 50) {
  477.         if(lseek(dataptr,0L,SEEK_END) != -1L) break;
  478.         DosSleep(100L);
  479.         tries++;
  480.     }
  481.     if(tries >= 50) {
  482.         printf("\nLocking conflict; aborting...(#1)\n");
  483.         return 0;
  484.     }
  485.  
  486.     pos = tell(dataptr);
  487.     x = (word)((pos / (long)sizeof(XMSG)) - 1L);
  488.     for(;x;x--) {
  489.  
  490.         tries = 0;
  491.         while(tries < 50) {
  492.             if(lseek(dataptr,(long)x * (long)sizeof(XMSG),SEEK_SET) != -1L) break;
  493.             DosSleep(100L);
  494.             tries++;
  495.         }
  496.         if(tries >= 50) {
  497.             printf("Locking contention...(#2)\n");
  498.             continue;
  499.         }
  500.  
  501.         tries = 0;
  502.         while(tries < 50) {
  503.             if((size_t)read(dataptr,&xmsg,sizeof(XMSG)) == sizeof(XMSG)) break;
  504.             DosSleep(100L);
  505.             tries++;
  506.             lseek(dataptr,(long)x * (long)sizeof(XMSG),SEEK_SET);
  507.         }
  508.         if(tries >= 50) {
  509.                         printf("Locking contention...(#3)\n");
  510.                         continue;
  511.         }
  512.  
  513.         if(xmsg.m_attr & MSGSCANNED) break;
  514.     }
  515.     return x;
  516. }
  517.