home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / ios_src / vcrunch.c < prev    next >
C/C++ Source or Header  |  1993-01-31  |  22KB  |  837 lines

  1. /*********************************************************************
  2.  
  3.                     IOS - messagebase compacter
  4.                     
  5.     Program : IOSmail
  6.     Source  : free
  7.     Author  : Rinaldo Visscher
  8.     Date    : 1991
  9.     
  10.     Crunch the messagebase.
  11. **********************************************************************/
  12.  
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <ext.h>
  16. #include <tos.h>
  17. #include <time.h>
  18. #include <stdio.h>
  19. #include "portab.h"
  20.  
  21. #include "defs.h"
  22. #include "ioslib.h"
  23. #include "modules.h"
  24. #include "lang.h"
  25.  
  26. #include "vars.h"
  27.  
  28. _filebuf    b_hdrrd;
  29. _filebuf    b_hdrwr;
  30. _filebuf    b_bodwr;
  31. _filebuf    b_renum;
  32. _filebuf    b_arbbs;
  33.  
  34. BOOLEAN check_deleted(VOID);
  35.  
  36. MLOCAL WORD    LedLstRd;
  37. MLOCAL WORD    Deleted;
  38. MLOCAL WORD    MSGSread;
  39.  
  40. LONG lmin(register LONG g1, register LONG g2)
  41. {
  42.     if (g1<g2) { return g1; }
  43.     return g2;
  44. } /* lmin */
  45.  
  46. WORD min(register WORD g1, register WORD g2)
  47. {
  48.     return g1<g2 ? g1 : g2;
  49. } /* min */
  50.  
  51. LONG lmax(register LONG g1, register LONG g2)
  52. {
  53.     return g1>g2 ? g1 : g2;
  54. } /* lmin */
  55.  
  56. VOID OpenLastRead(VOID)
  57. {
  58.     struct stat statbuf;
  59.     BYTE tmp[80];
  60.     
  61.     if (doQbbslr) {                    /* if we want to update .BBS    */
  62.         sprintf(tmp, "%sLASTREAD.BBS", Qbbslr);
  63.         if (stat(tmp, &statbuf) < 0) {
  64.             doQbbslr = FALSE;
  65.         } else {
  66.             g_users = (WORD)(statbuf.st_size / LBBSRECSIZE);
  67.             if (g_users > 0) {
  68.                 if ((F_LSTBBS = Fopen(tmp, FO_RW)) < 0) {
  69.                     doQbbslr = FALSE;
  70.                 }
  71.             }
  72.         }
  73.     }
  74. } /* OpenLastRead */
  75.  
  76. VOID SetLastReadPtr (WORD area, WORD value)
  77. {
  78.     LONG pos;
  79.  
  80.     if (LRD==NULL) return;
  81.     
  82.     pos = (LONG) (sizeof(WORD) * (area+g_lsttype));
  83.     
  84.     /* to correct positition */
  85.     fseek(LRD,pos,0);
  86.     
  87.     fwrite((BYTE *)&value, sizeof(WORD), 1,LRD);
  88.     
  89.     giveTIMEslice();
  90.     
  91.     if (/*area == mailarea &&*/ g_lsttype == 2) {
  92.     
  93.         /* this we do just if we are using LED's interpretation of the    */
  94.         /* lastread.ced file. See developmnt document                    */
  95.         
  96.         pos = (LONG) (sizeof(WORD) * 1);
  97.         
  98.         /* to correct positition */
  99.         
  100.         fseek(LRD,pos,0);
  101.         fwrite((BYTE *)&value, sizeof(WORD), 1,LRD);
  102.         giveTIMEslice();
  103.     }
  104. } /* SetLastReadPtr */
  105.  
  106. WORD GetLastReadPtr (WORD Area)
  107. {
  108.     LONG pos;
  109.     WORD i,n;
  110.     if (LRD==NULL) { return 0; }    /* File isn't open...                */
  111.     
  112.     fseek(LRD,0L,2);
  113.     
  114.     /* if we have a typ 2 lastread.ced (LED) and this is the mailarea,    */
  115.     /* we have to read integer number 1 from the file. [0..??]            */
  116.     
  117.     pos = g_lsttype != 2 ? (LONG) (sizeof(WORD) * (Area+g_lsttype)) : sizeof(WORD) * 1;
  118.     if (pos>ftell(LRD)) {            /* to prevent reading byond eof        */
  119.         n = (WORD)(pos-ftell(LRD))/2;
  120.         for (i=0; i<n; i++) {
  121.             putc (0, LRD);
  122.             putc (0, LRD);
  123.             putc (0, LRD);
  124.             putc (0, LRD);
  125.             giveTIMEslice();
  126.         }
  127.         return 0;
  128.     }
  129.     fseek(LRD,pos,0);
  130.     fread((BYTE *)&i, sizeof(WORD), 1, LRD);
  131.     giveTIMEslice();
  132.     return i;
  133. } /* GetLastReadPtr */
  134.  
  135. WORD Aopen(VOID)
  136. {
  137.     struct stat f;
  138.     WORD driveno;
  139.         
  140.     sprintf(oldmsg,"%s.MSG",Areapath[g_curarea]);
  141.     sprintf(newmsg,"%s.MTP",Areapath[g_curarea]);
  142.     sprintf(oldhdr,"%s.HDR",Areapath[g_curarea]);
  143.     sprintf(newhdr,"%s.HTP",Areapath[g_curarea]);
  144.  
  145.     HDR = MSG = newHDR = newMSG = -1;    /* all files still closed        */
  146.  
  147.     if ((HDR=Fopen(oldhdr, FO_RW))<0) {
  148.         HDR=Fcreate(oldhdr, NOATTRIB);
  149.     }
  150.     if (!stat(oldhdr, &f)) {
  151.         g_hdr_fsize = f.st_size;
  152.     }
  153.     if (!stat(oldmsg, &f)) {
  154.         g_bod_fsize = f.st_size;
  155.     }
  156.     
  157.     if (!g_bod_fsize && g_hdr_fsize) {
  158.         return (AR_MSGERR);
  159.     }
  160.     
  161.     giveTIMEslice();
  162.     
  163.     /* compute number of hdrs in the file...                            */    
  164.     
  165.     g_nrhdrs = (WORD) (g_hdr_fsize / sizeof(MSGHEADER));
  166.     
  167.     /* Here the free diskspace is checked, whenever there seems to be     */
  168.     /* to little of it. Initially, g_dfree contains only zero's.        */
  169.     /* In this way, diskspace checking is performed as little as possib    */
  170.     
  171.     if (g_hdr_fsize + g_bod_fsize >= g_dfree[driveno = Dgetdrv()]) {
  172.         g_dfree[driveno] = diskfree(driveno);
  173.         if (g_hdr_fsize + g_bod_fsize >= g_dfree[driveno]) {
  174.             Fclose(HDR);
  175.             return AR_DISKFREE;
  176.         }
  177.     }
  178.     if (g_nrhdrs < Areamin[g_curarea]) {
  179.         if (check_deleted() == FALSE) {
  180.             Fclose(HDR);
  181.             return AR_TOSMALL;
  182.         }
  183.         lseek(HDR, 0L, SEEK_SET);
  184.         return AR_OK;
  185.     }
  186.     if (g_nrhdrs > MAXMSGS) {
  187.         return AR_TOBIG;
  188.     }
  189.  
  190.     if (HDR < 0) {
  191.         log_line(6,Logmessage[M__ERROR_OPENING_AREA]);
  192.         clean_mess();
  193.         return AR_IOERR;
  194.     }
  195.     return AR_OK;
  196. } /* Aopen */
  197.  
  198. BOOLEAN check_deleted() {
  199.     MSGHEADER g_hdr;
  200.     WORD i = g_nrhdrs;
  201.     
  202.     while( i > 0) {
  203.         Fread(HDR, sizeof (MSGHEADER), &g_hdr);
  204.         if ((g_hdr.flags & DELETED)) return (TRUE);
  205.         i--;
  206.     }
  207.     return (FALSE);
  208. }
  209.  
  210. VOID clean_mess(VOID)
  211. {
  212.     Fclose(HDR);
  213.     Fclose(MSG);
  214.     giveTIMEslice();
  215.     Fclose(newHDR);
  216.     Fclose(newMSG);
  217.     giveTIMEslice();
  218.     unlink(newhdr);
  219.     unlink(newmsg);
  220.     giveTIMEslice();
  221. } /* clean_mess */
  222.  
  223. VOID buf_init(_filebuf *bp, LONG bsize, LONG itemsize)
  224. {
  225.     bp->size = bsize;                        /* it's size in bytes    */
  226.     bp->start = (BYTE *) malloc(bp->size);    /* allocate space        */
  227.     bp->curpos = bp->start;                    /* current pos = start    */
  228.     bp->level = 0;                            /* no items in buffer    */
  229.     bp->maxitem = (bp->size/itemsize);        /* max no. items in buf    */
  230.     
  231.     if (bp->start == NULL || bp->maxitem == 0) {
  232.         log_line(6,Logmessage[M__CANT_CREATE_BUFFER],bsize,itemsize);
  233.         terminate(2);
  234.     }
  235. } /* buf_init */
  236.  
  237. VOID buf_free(_filebuf *bp)
  238. {
  239.     free(bp->start);
  240.     bp->start = NULL;
  241. } /* buf_free */
  242.  
  243. VOID up_lastbbs(WORD areanr, WORD highest)
  244. {
  245.     _filebuf b_lstbbs;
  246.     WORD leftrec = g_users;    /* total no. of records to process            */
  247.     WORD chunckcnt;            /* no. of records in current chunck            */
  248.     WORD amount;                /* to temp. store chunckcnt                    */
  249.     WORD *changep;            /* used to traverse buffer and change        */
  250.     LONG size;                /* compute buffersize, to please Mes-Dos...    */
  251.  
  252.     size = lmin(coreleft()-4096L, g_users*LBBSRECSIZE);
  253. #if SMALLBUF 
  254.     size = lmin(size, SMBUFSIZE);
  255. #endif
  256.     buf_init(&b_lstbbs, size, LBBSRECSIZE);
  257.  
  258.     Fseek(0L, F_LSTBBS, 0);    /* rewind to beginning of file                */
  259.     while (leftrec > 0) {
  260.         amount = chunckcnt = (WORD)lmin(b_lstbbs.maxitem, leftrec);
  261.         Fread(F_LSTBBS,amount * LBBSRECSIZE,b_lstbbs.start);
  262.         giveTIMEslice();
  263.         changep = (WORD *)b_lstbbs.start;
  264.         changep = &changep[areanr];
  265.         while (chunckcnt > 0) {
  266.             if (*changep > 0 && *changep <= g_nrhdrs) {
  267.                 *changep = g_newnum[*changep];
  268.             } else {
  269.                 *changep = highest;
  270.             }
  271.             /* Now this was a nasty thing to find...                    */
  272.             changep += (LBBSRECSIZE / sizeof(WORD));
  273.             --chunckcnt;
  274.         }
  275.         /* rewind relative to current pos                                 */
  276.         Fseek(-amount * LBBSRECSIZE, F_LSTBBS, 1);
  277.         /* and write back again processed records                        */
  278.         Fwrite(F_LSTBBS, amount * LBBSRECSIZE, b_lstbbs.start);
  279.         giveTIMEslice();
  280.         leftrec -= amount;
  281.     } /* while leftrec > 0 */
  282.  
  283. } /* up_lastbbs */
  284.  
  285. WORD msgok(MSGHEADER *hp, WORD area)
  286. {
  287.     register LONG age;
  288.  
  289.     giveTIMEslice();
  290.  
  291.     g_curtime = time (NULL);
  292.     if (hp->flags & DELETED) {
  293.         g_amhdr--;
  294.         return (MSGDELETE);
  295.     }
  296.     
  297.     if ((hp->flags & KILLSEND) && (hp->flags & SENT)) {
  298.         g_amhdr--;
  299.         return (MSGDELETE);
  300.     }
  301.  
  302.     if (Areakeep[g_curarea] == KEEPMSGS) {
  303.         g_amhdr--;
  304.         return (MSGOK);
  305.     }
  306.         
  307.     age = (g_curtime - hp->create) / SECSDAY;
  308.     
  309.     if (Areaday[area] < age) {
  310.         g_amhdr--;
  311.         return (MSGDELETE);
  312.     }
  313.     
  314.     if (g_amhdr > maxmsgs) {
  315.         g_amhdr --;
  316.         return (MSGDELETE);
  317.     }
  318.     
  319.     return (MSGOK);
  320. } /* msgok */
  321.  
  322. WORD cleanEcho(VOID)
  323. {
  324.     WORD curdeleted;
  325.     WORD resthdrs;
  326.     WORD writhdrs;                /* totaal aantal weggeschreven hdrs     */
  327.     WORD oldno        = 0;
  328.     WORD newno        = 0;
  329.     WORD error         = FALSE;
  330.     WORD hloop;
  331.     WORD i;                        /* loopvar for removing 0's             */
  332.     WORD curmax;                    /* hold highest log_line number            */
  333.     WORD from_hdr;
  334.     LONG readfrom    = FLAG;
  335.     LONG readto        = FLAG;
  336.     LONG amount;
  337.     LONG spaceleft;
  338.     LONG onepart;
  339.     LONG size;            /* to compute buffer size into...                */
  340.     MSGHEADER *chp;
  341.     MSGHEADER *whp;
  342.     
  343.     if (!g_hdr_fsize) return (0); 
  344.     
  345.     g_amhdr = g_nrhdrs;
  346.     
  347.     g_newnum = (WORD *)calloc(g_nrhdrs, sizeof(WORD));
  348.  
  349.     onepart    = ((coreleft() / TOTPART) / 2048 * 2048);    /* dividable by 2K        */ 
  350.     
  351.     size = lmin(onepart * BODWRPART, g_bod_fsize);
  352. #if SMALLBUF
  353.     size = lmin(size,SMBUFSIZE);
  354. #endif
  355.     if (!size) return (0);
  356.     
  357.     buf_init(&b_bodwr, size, 1L);
  358.  
  359.     /* onepart is recomputed, because maybe the above SMALLBUF thin
  360.        caused the biggest buffer b_bodwr to be truncated, in wich case
  361.        there is aditional memory for the hdr buffers. Get it?            */
  362.        
  363.     onepart    = ((coreleft() / TOTPART) / 2048 * 2048);    /* dividable by 2K        */ 
  364.     
  365.     size = lmin(onepart * HDRRDPART, g_hdr_fsize);
  366. #if SMALLBUF
  367.     size = lmin(size, SMBUFSIZE);
  368. #endif
  369.     buf_init(&b_hdrrd, size, sizeof(MSGHEADER));
  370.     
  371.     size = lmin(onepart * HDRWRPART, g_hdr_fsize);
  372. #if SMALLBUF
  373.     size = lmin(size,SMBUFSIZE);
  374. #endif
  375.     buf_init(&b_hdrwr,size,sizeof(MSGHEADER));
  376.  
  377.     g_offset = 0L;
  378.     whp = (MSGHEADER *)(b_hdrwr.start);
  379.     resthdrs = g_nrhdrs;    /* yet to process, g_nrhdrs set in Aopen    */
  380.     writhdrs = 0;            /* none written yet                            */
  381.     
  382.     while (resthdrs > 0) {
  383.         if (b_hdrrd.level == 0) {    /* no hdrs left in input buffer        */
  384.             b_hdrrd.level = min((WORD)b_hdrrd.maxitem,resthdrs);
  385.             Fread(HDR,b_hdrrd.level*sizeof(MSGHEADER),b_hdrrd.start);
  386.             giveTIMEslice();
  387.             chp = (MSGHEADER *)(b_hdrrd.start);
  388.         }
  389.         
  390.         /* At this point, chp points to the hdr next to be processed in memory.    */
  391.         
  392.         --resthdrs;                /* processing this one                    */
  393.         --b_hdrrd.level;        /* this is where it came from            */
  394.         
  395.         if (msgok(chp,g_curarea)) {
  396.             if (b_hdrwr.level == b_hdrwr.maxitem) { /* hdr output full    */
  397.                 if (newHDR < 0 &&
  398.                    (newHDR=Fcreate(newhdr, NOATTRIB)) < 0) {
  399.                     log_line(6,Logmessage[M__CANT_OPEN_HEADER],newhdr);
  400.                     goto CE_ERROR;    /* at the end of this function        */
  401.                 }
  402.                 writhdrs += (WORD)b_hdrwr.level;    /* look at renumbering!    */
  403.                 Fwrite(newHDR,b_hdrwr.level*sizeof(MSGHEADER),b_hdrwr.start);
  404.                 giveTIMEslice();
  405.                 whp = (MSGHEADER *)(b_hdrwr.start);
  406.                 b_hdrwr.level = 0;    /* empty now    */
  407.             } else {
  408.                 if(b_hdrwr.level > b_hdrwr.maxitem) {
  409.                     log_line(6,Logmessage[M__HEADER_OVERFLOW]);
  410.                 
  411.                     clean_mess();
  412.                     terminate(10);
  413.                 }
  414.             }
  415.             
  416.             /* now we are sure there is space in the output buffer        */
  417.             
  418.             memcpy(whp,chp,sizeof(MSGHEADER));        /* copy it            */
  419.             whp->Mstart = g_offset;                    /* in new file        */
  420.             ++whp;                /* next hdr copied here    ...                */
  421.             ++b_hdrwr.level;    /* and another 1 added to outputbuffer    */
  422.             g_offset += chp->size;
  423.             if (readfrom == FLAG) {    /* only the first time per area        */
  424.                 readfrom = chp->Mstart;
  425.                 readto = chp->Mstart + chp->size;    /* TO, not including!    */
  426.             } else {
  427.                 if (readto == chp->Mstart) {
  428.                     readto += chp->size;    /* for a continues chunk    */
  429.                 } else {
  430.                     if(MSG < 0 && 
  431.                       (MSG = Fopen(oldmsg, FO_RW)) < 0 &&
  432.                       (MSG = Fcreate(oldmsg, NOATTRIB)) < 0) {
  433.                         log_line(6,Logmessage[M__CANT_OPEN_HEADER],newhdr);
  434.                         goto CE_ERROR;    /* at the end of this function    */
  435.                     }
  436.                     Fseek(readfrom,MSG,0);
  437.                     giveTIMEslice();
  438.                     
  439.                     /* this while reads the from-to chunck of the file,    */
  440.                     /* and only writes out the buffer if verry little     */
  441.                     /* free space remains in it. So it is possible that    */
  442.                     /* this while reads only 1 log_line body, and writes    */
  443.                     /* nothing at all. body remains in mem buffer        */
  444.                     
  445.                     while (readfrom != readto) {
  446.                     
  447.                         /* is it possible to compare these things????    */
  448.                         
  449.                         spaceleft = b_bodwr.size - (b_bodwr.curpos - b_bodwr.start);
  450.                         amount = lmin(spaceleft,readto - readfrom);
  451.                         Fread(MSG,amount,b_bodwr.curpos);
  452.                         giveTIMEslice();
  453.                         b_bodwr.curpos += amount;
  454.                         readfrom += amount;
  455.                         spaceleft = b_bodwr.size - (b_bodwr.curpos - b_bodwr.start);
  456.                         if (spaceleft < 10*1024 ) {
  457.                             if(newMSG < 0 &&
  458.                                (newMSG = Fcreate(newmsg, NOATTRIB)) < 0) {
  459.                                 log_line(6,Logmessage[M__CANT_OPEN_AREA]
  460.                                             ,newmsg);
  461.                                 goto CE_ERROR;    /* at the end of this function    */
  462.                             }
  463.                             Fwrite(newMSG,b_bodwr.curpos - b_bodwr.start,b_bodwr.start);
  464.                             giveTIMEslice();
  465.                             b_bodwr.curpos = b_bodwr.start;
  466.                         }
  467.                     }
  468.                     readfrom = chp->Mstart;
  469.                     readto = readfrom + chp->size;                
  470.                 }
  471.             }
  472.             g_newnum[oldno] = newno;    /* for renumbering    */
  473.             ++newno;    
  474.         } /* if msgok */
  475.         ++oldno;
  476.         ++chp;
  477.  
  478.         if (MSGSread <= LedLstRd) {
  479.             Deleted ++;
  480.             MSGSread++;
  481.         }
  482.  
  483.     } /* while resthdrs > 0    */
  484.  
  485.     if ((curdeleted = (oldno -newno)) > 0 && !error) {
  486.     
  487.         /* we only need to write buffers to files if there has been a    */
  488.         /* change in the log_line base.                                    */
  489.         
  490.         if (MSG < 0 && 
  491.            (MSG = Fopen(oldmsg, FO_RW)) < 0 &&
  492.            ((MSG = Fcreate(oldmsg, NOATTRIB)) < 0)) {
  493.             log_line(6,Logmessage[M__CANT_OPEN_HEADER],newhdr);
  494.             goto CE_ERROR;    /* at the end of this function    */
  495.         }
  496.         giveTIMEslice();
  497.         
  498.         if (newMSG < 0 &&
  499.             ((newMSG = Fcreate(newmsg, NOATTRIB)) < 0)) {
  500.             log_line(6,Logmessage[M__CANT_OPEN_AREA],newmsg);
  501.             goto CE_ERROR;    /* at the end of this function    */
  502.         }
  503.         Fseek(readfrom,MSG,0);
  504.         while (readfrom != readto) {
  505.             /* is it possible to compare these things????    */
  506.             spaceleft = b_bodwr.size - (b_bodwr.curpos - b_bodwr.start);
  507.             amount = lmin(spaceleft,readto - readfrom);
  508.             Fread(MSG,amount,b_bodwr.curpos);
  509.             giveTIMEslice();
  510.             b_bodwr.curpos += amount;
  511.             readfrom += amount;
  512.             if (b_bodwr.curpos != b_bodwr.start) {
  513.                 Fwrite(newMSG,b_bodwr.curpos - b_bodwr.start,b_bodwr.start);
  514.                 giveTIMEslice();
  515.                 b_bodwr.curpos = b_bodwr.start;
  516.             }
  517.         }
  518.         if (b_bodwr.curpos != b_bodwr.start) {
  519.             Fwrite(newMSG,b_bodwr.curpos - b_bodwr.start,b_bodwr.start);
  520.             giveTIMEslice();
  521.             b_bodwr.curpos = b_bodwr.start;
  522.         }
  523.         
  524.         /* and now... for the renumbering!                                */    
  525.         /* First we steal the memory from the no longer used buffer        */
  526.         /* b_bodwr, by first freeing WORD, and then it is reclaimed by    */
  527.         /* buf_init.                                                    */ 
  528.         
  529.         size = b_bodwr.size;
  530.         buf_free(&b_bodwr);
  531.         
  532.         if (!size) return (0);
  533.         
  534.         buf_init(&b_renum,size,1L);
  535.         
  536.         /* First we handle the hdrs already written to the newHDR file    */
  537.         /* (if any exist)                                                */
  538.         
  539.         if (writhdrs > 0) {
  540.             Fseek(0L,newHDR,0);        /* to begin of file                    */
  541.             from_hdr = 0;
  542.             while (from_hdr < writhdrs) {
  543.                 amount = lmin(writhdrs - from_hdr, b_renum.maxitem);
  544.                 Fread(newHDR,amount * sizeof(MSGHEADER),b_renum.start);
  545.                 giveTIMEslice();
  546.                 chp = (MSGHEADER *)b_renum.start;
  547.                 for (hloop = (WORD)amount; hloop > 0; --hloop) {
  548.                     if (chp->parent != 0) {
  549.                         chp->parent = g_newnum[chp->parent];
  550.                     }
  551.                     ++chp;
  552.                 }
  553.                 Fseek(-amount * sizeof(MSGHEADER),newHDR,1);
  554.                 Fwrite(newHDR,amount * sizeof(MSGHEADER),b_renum.start);
  555.                 giveTIMEslice();
  556.                 from_hdr += (WORD)amount;
  557.             }
  558.         }
  559.         
  560.         /* and then the hdrs in the original hdr output buffer            */
  561.         
  562.         if (b_hdrwr.level >= 0) { /* buffer contains some hdrs */
  563.             if (newHDR < 0 &&
  564.                (newHDR=Fcreate(newhdr, NOATTRIB)) < 0) {
  565.                 log_line(6,Logmessage[M__CANT_OPEN_HEADER],newhdr);
  566.                 goto CE_ERROR;    /* at the end of this function    */
  567.             }
  568.             chp = (MSGHEADER *)b_hdrwr.start;
  569.             for (hloop = (WORD)b_hdrwr.level; hloop > 0; --hloop) {
  570.                 if (chp->parent != 0) {
  571.                     chp->parent = g_newnum[chp->parent];
  572.                 }
  573.                 ++chp;
  574.             }
  575.             Fwrite(newHDR,b_hdrwr.level*sizeof(MSGHEADER),b_hdrwr.start);
  576.             giveTIMEslice();
  577.  
  578.             /* no need to reinit .level or  whp...        */
  579.         }
  580.         buf_free(&b_renum);        /* This frees also the memory used for    */
  581.         buf_free(&b_hdrwr);        /* the actual buffer. We need it later    */
  582.         buf_free(&b_hdrrd);        /* in up_lastbbs                        */
  583.         
  584.         /* first we process the g_newnum array, to get some 0's out.        */
  585.         /* the next piece of code changes the row 0 0 1 0 2 3 4 0 0 5 6 0    */
  586.         /* into the row                           0 0 1 1 2 3 4 4 4 5 6 6    */
  587.         /* so that if a log_line is deleted you get the last valid log_line    */
  588.         /* before the deleted one as the log_line you last read.            */
  589.         
  590.         for (i=curmax=0; i<g_nrhdrs; ++i) {
  591.             if (g_newnum[i] == 0) {
  592.                 g_newnum[i] = curmax;
  593.             } else {
  594.                 curmax = g_newnum[i];
  595.             }
  596.         }
  597.         SetLastReadPtr(g_curarea,g_newnum[GetLastReadPtr(g_curarea)]);
  598.         if (doQbbslr) {
  599.             up_lastbbs(g_curarea,curmax);
  600.         }
  601.     } else {
  602.         buf_free(&b_bodwr);    
  603.         buf_free(&b_hdrwr);    
  604.         buf_free(&b_hdrrd);    
  605.     }
  606.     free(g_newnum);
  607.     return curdeleted ;    /* if 0 messages are deleted, original files    */
  608.                         /* are kept by Aclose...                        */
  609.                         /* This is the normal end of the function!!!    */
  610.                         
  611. CE_ERROR:    /* A file io error has occured. This can happen at 6         */
  612.             /* clearly marked places *in*this*function*. A goto is used */
  613.             /* to bail out in those rare cases...                        */
  614.     buf_free(&b_bodwr);    
  615.     buf_free(&b_hdrwr);    
  616.     buf_free(&b_hdrrd);    
  617.     free(g_newnum);
  618.     return 0;    /* causes original files left untouched, files will be    */                        
  619.                 /* closed by Aclose in a minute...                        */
  620. } /* cleanEcho */
  621.  
  622. VOID Aclose(WORD changed)
  623. {
  624.     WORD ok;
  625.     ok = (Fclose(newMSG) == 0);
  626.     ok &= (Fclose(newHDR) == 0);
  627.     giveTIMEslice();
  628.  
  629.     Fclose(HDR);
  630.     Fclose(MSG);
  631.     giveTIMEslice();
  632.  
  633.     if (!changed) { /* if no messages deleted, files not changed, so...    */
  634.         unlink(newmsg);
  635.         unlink(newhdr);
  636.         giveTIMEslice();
  637.         return;
  638.     }
  639.     if (ok)    { /* ok means files are allright, wouldn't you think so?    */
  640.         unlink(oldmsg);
  641.         rename(newmsg,oldmsg);
  642.         giveTIMEslice();
  643.         unlink(oldhdr);
  644.         rename(newhdr,oldhdr);
  645.         giveTIMEslice();
  646.     } else {
  647.         unlink(newmsg);
  648.         giveTIMEslice();
  649.         unlink(newhdr);
  650.         log_line(6,Logmessage[M__CANT_CLOSE_MSG]);
  651.     }
  652.     return;
  653. } /* Aclose */
  654.  
  655. VOID deinitialize(VOID)
  656. {
  657.     if (SIZE != NULL) { fclose(SIZE); }
  658.     if (LRD != NULL) { fclose(LRD); }
  659.     giveTIMEslice();
  660.     if (F_LSTBBS >= 0) {
  661.         Fclose(F_LSTBBS);
  662.         giveTIMEslice();
  663.     }
  664.     if (doled) {
  665.         if (!doscanmail)
  666.             write_lednew();
  667.     }
  668. } /* deinitialize */
  669.  
  670. LONG diskfree(WORD drvno)
  671. {
  672.     DISKINFO diskbuf;
  673.  
  674.     Dfree(&diskbuf,drvno+1);
  675.     giveTIMEslice();
  676.     return (diskbuf.b_free*diskbuf.b_clsiz*diskbuf.b_secsiz);
  677. } /* diskfree */
  678.  
  679. VOID compactMSGbase(WORD mode)
  680. {
  681.     WORD areadeleted, haveareas, start, i;
  682.     BOOLEAN Ok = FALSE;
  683.     
  684.     if (doimport && defcrunch == AFTERIMPORT) Ok = TRUE;
  685.     if (doscanmail && defcrunch == AFTERSCAN) Ok = TRUE;
  686.     if (defcrunch == CRUNCHALWAYS) Ok = TRUE;
  687.     if (mode == CRUNCHSPECIALS) Ok = TRUE;
  688.     
  689.     if (Ok == FALSE) return;
  690.     
  691.     log_line(6,Logmessage[M__COMPACTING]);
  692.  
  693.     OpenLastRead();
  694.  
  695.     haveareas = msgareas;
  696.     
  697.     if (mode == CRUNCHSPECIALS)
  698.         start = msgareas;
  699.     else
  700.         start = 0;
  701.         
  702.     if (strlen(mailarea)) {
  703.         Areaname[haveareas] = strdup("FidoNETMAIL");
  704.         Areapath[haveareas] = mailarea;
  705.         Areamin [haveareas] = mailmin;
  706.         Areakeep[haveareas] = mailkeep;
  707.         Areaday[haveareas++] = maildays;
  708.     }
  709.     
  710.     if (strlen(trasharea)) {
  711.         Areaname[haveareas] = strdup ("TRASHAREA");
  712.         Areapath[haveareas] = trasharea;
  713.         Areamin [haveareas] = trashmin;
  714.         Areakeep[haveareas] = trashkeep;
  715.         Areaday[haveareas++] = trashdays;
  716.     }
  717.     
  718.     if (strlen(privatebox)) {
  719.         Areaname[haveareas] = strdup("PRIVATEMAIL");
  720.         Areapath[haveareas] = privatebox;
  721.         Areamin [haveareas] = pvtboxmin;
  722.         Areakeep[haveareas] = pvtkeep;
  723.         Areaday[haveareas++] = pvtboxdays;
  724.     }
  725.  
  726.     if (strlen(dupearea)) {
  727.         Areaname[haveareas] = strdup("DUPE_AREA");
  728.         Areapath[haveareas] = dupearea;
  729.         Areamin [haveareas] = dupemin;
  730.         Areakeep[haveareas] = dupekeep;
  731.         Areaday[haveareas++] = dupedays;
  732.     }
  733.     
  734.     for (g_curarea = start; g_curarea < haveareas; g_curarea++) {
  735.         if (Dareas[g_curarea] == 1) continue;
  736.  
  737.         Deleted = LedLstRd = MSGSread = 0;
  738.         
  739.         if (nled) {
  740.             for (i = 0;    i < nled ; i++) {
  741.                 if (!stricmp (Areaname [ g_curarea], "privatemail")) {
  742.                     if (!stricmp (Lareaname[i], "privateboxarea") ||
  743.                         !strnicmp (Lareaname[i], "privatemail", 11)) {
  744.                         
  745.                         LedLstRd = Lledmsgs[i];
  746.                         break;
  747.                     }
  748.                 }
  749.                 
  750.                 if (!stricmp (Areaname [g_curarea], Lareaname [i])) {
  751.                     LedLstRd = Lledmsgs[i];
  752.                     break;
  753.                 }
  754.             }
  755.         }
  756.         
  757.         hprintf (S_AREA, "%s", Areaname[g_curarea]);
  758.  
  759.         switch (Aopen()) {
  760.         case AR_OK          :    /* printf("%4d",g_nrhdrs); */
  761.                             
  762.                             areadeleted = cleanEcho();    /* delete messages            */
  763.                             g_totdel += areadeleted;
  764.                         
  765.                             if (doled) Update_LED(Deleted);
  766.                             
  767.                             hprintf (S_DELETED, "%d", g_totdel);
  768.                             
  769.                             g_totleft += g_nrhdrs - areadeleted;
  770.                             if (areadeleted != 0) {
  771.                                 log_line(3,Logmessage[M__MSGS_DELETED],
  772.                                 Areaname[g_curarea],areadeleted);
  773.                             } else {
  774.                                 if (g_nrhdrs)
  775.                                     log_line(3,Logmessage[M__NOTHING_DELETED],
  776.                                     Areaname[g_curarea]);
  777.                                 else
  778.                                     log_line(3,Logmessage[M__EMPTY_AREA],
  779.                                     Areaname[g_curarea]);
  780.                             }
  781.                             
  782.                             Aclose(areadeleted != 0);    /* close the current area   */
  783.                                 
  784.                             break;
  785.         case AR_TOSMALL      :    if (g_nrhdrs > 0) {
  786.                                 g_totleft += g_nrhdrs;
  787.                                 log_line(3,Logmessage[M__MINIMUM_MSGS],
  788.                                         Areaname[g_curarea],g_nrhdrs,Areamin[g_curarea]);
  789.                             } else {
  790.                                 log_line(3,Logmessage[M__EMPTY_AREA],
  791.                                 Areaname[g_curarea]);
  792.                             }
  793.                             break;
  794.         case AR_TOBIG      :    g_totleft += g_nrhdrs;
  795.                             log_line(4,Logmessage[M__MAXIMUM_MSGS],
  796.                                     Areaname[g_curarea],g_nrhdrs,MAXMSGS);
  797.                             break;
  798.         case AR_IOERR      :    log_line(6,Logmessage[M__FILE_IO_ERROR]);
  799.                             break;
  800.         case AR_DISKFREE  :    g_totleft += g_nrhdrs;
  801.                             log_line(6,Logmessage[M__NO_DISKSPACE],g_nrhdrs);
  802.                             break;
  803.         case AR_MSGERR      : log_line(6, Logmessage[M__BODY_ERROR]);
  804.                             break;
  805.         default              :    log_line(6,Logmessage[M__COMPILER_ERROR]);
  806.         }
  807.     }
  808.     
  809.     if(g_totleft || g_totdel)
  810.         log_line(3,Logmessage[M__MSGS_RESUMEND], g_totdel, g_totleft);
  811.  
  812.     deinitialize();
  813. }
  814.  
  815. VOID Update_LED(WORD deleted) {
  816.     WORD i;
  817.     
  818.     if (!deleted) return;
  819.     
  820.     for (i=0; i < nled; i++) {
  821.         if (!stricmp (Areaname [ g_curarea], "privatemail")) {
  822.             if (!stricmp (Lareaname[i], "privateboxarea") ||
  823.                 !strnicmp (Lareaname[i], "privatemail", 11)) {
  824.                 
  825.                 Lledmsgs[i] -= deleted;
  826.                 break;
  827.             }
  828.         }
  829.  
  830.         if (!stricmp(Lareaname[i], Areaname[g_curarea])) {
  831.             Lledmsgs[i] -= deleted;
  832.             if (Lledmsgs[i] < 0) Lledmsgs[i] = 0;
  833.             break;
  834.         }
  835.     }
  836. }
  837.