home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / BBS / MISC / XDEV_117.ZIP / XMSG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-16  |  27.6 KB  |  1,171 lines

  1. /* XMSG Message utility program for XBBS */
  2. /* Copyright (c) 1989/90 by M. Kimes...all rights reserved */
  3.  
  4. /* NOTE:  This doesn't share yet... */
  5.  
  6. #include "msgg.h"
  7. #include "stdlib.h"
  8.  
  9. void   cdecl  deinit(void);
  10. int    pascal free_buf(char bufnum);
  11. char * pascal lstrip(char *a);
  12. char * pascal rstrip(char *a);
  13. char * pascal stripcr (char *a);
  14. int    pascal set_buf (FILE *fp,char bufnum);
  15. int    pascal free_bufs (void);
  16. void   pascal kill_junk (word number1);
  17. void   pascal readconfig(void);
  18. void   pascal domsg(word,char,char);
  19. int    pascal checkfile(char *);
  20. void   pascal trim(word,word);
  21. void   pascal days(word,word);
  22. ulong  pascal diffdays(struct date *);
  23. int    cdecl  breakhandler(void);
  24. char * pascal stristr (char *t, char *s);
  25. char * pascal unpack_msg (char **hold);
  26. char * pascal pack_msg (char *hold,struct _xmsg *msg);
  27.  
  28. struct   ffblk f;
  29. struct   _config conf;
  30. unsigned int huge *lastarray=NULL;
  31. char     killbackups;
  32. char     dontanalyze=1;
  33. char     dontpack=0;
  34. char     didbreak=0;
  35. struct   _xmsg msg;
  36. char     messpath[80]="";
  37. char     il[256];
  38. char      argarray[12][128];
  39. char     fromname[36];
  40. char     toname[36];
  41. char      subj[64];
  42. char     partial;
  43. char      matchany;
  44. char     verbose=0;
  45. word      compress_size;
  46. char      uncompress;
  47. word     textsize;
  48. word     codesize;
  49.  
  50. #define NUMBUFS 5
  51.  
  52. char *buf[NUMBUFS]={NULL,NULL,NULL,NULL,NULL};
  53.  
  54. #define MYBUFSIZE 16384
  55.  
  56. extern unsigned _Cdecl _stklen = 6144;    /* Stack length */
  57.  
  58.  
  59.  
  60.  
  61. void cdecl main (int argc,char *argv[]) {
  62.  
  63.  FILE *fp;
  64.  word register x;
  65.  word register y;
  66.  word number1;
  67.  word number2;
  68.  word numdays=0;
  69.  word buffer=0;
  70.  char private=0;
  71.  word trimto=0;
  72.  char tempstring[30]="";
  73.  char mainarg;
  74.  char *p;
  75.  char templine[256]="";
  76.  
  77.   fprintf(stderr,"\n\n\x1b[0;1;37mXMSG (XBBS message base handler) copyright (c) 1989/90 by M. Kimes\n");
  78.   fprintf(stderr,"Compiled: %s  %s",__DATE__,__TIME__);
  79.  
  80.   *conf.messpath=0;
  81.   conf.nolmrs=0;
  82.   readconfig();
  83.   if(conf.nolmrs) {
  84.     lastarray=(unsigned int huge*)malloc(conf.nolmrs * sizeof(word));
  85.     if (lastarray==NULL) {
  86.         printf("\nOOM for LMRs\n");
  87.         exit(1);
  88.     }
  89.   }
  90.   ctrlbrk(breakhandler);
  91.   atexit(deinit);
  92.   strncpy(messpath,conf.messpath,79);
  93.   messpath[79]=0;
  94.  
  95.   if(argc<2) goto BadArgs;
  96.   if(toupper(argv[1][1])=='A') {
  97.         if((fp=fopen(&argv[1][2],"rt"))==NULL) {
  98.             printf("\nUnable to open action file %s\n",&argv[1][2]);
  99.             goto BadArgs;
  100.         }
  101.         goto StartHere;
  102.   }
  103.   if (argc<4) goto BadArgs;
  104.   number1=(word)atol(argv[2]);
  105.   number2=(word)atol(argv[3]);
  106.  
  107.   for (x=0;x<argc;x++) {
  108.     strupr(argv[x]);
  109.   }
  110.  
  111.   if (!strcmp(argv[1],"-P")) {
  112.     if (argc>4) {
  113.         x=4;
  114.         goto StartHere;
  115.     }
  116.   }
  117.   if (!strcmp(argv[1],"-D")) {
  118.     if (argc<5) goto BadArgs;
  119.     numdays=(word)atol(argv[4]);
  120.     if (!numdays) goto BadArgs;
  121.     if (argc>5) {
  122.         x=5;
  123.         goto StartHere;
  124.     }
  125.   }
  126.   if (!strcmp(argv[1],"-T")) {
  127.     if (argc<5) goto BadArgs;
  128.     trimto=(word)atol(argv[4]);
  129.     if (!trimto) goto BadArgs;
  130.     if (argc>5) {
  131.         x=5;
  132.         goto StartHere;
  133.     }
  134.   }
  135.   if (!strcmp(argv[1],"-R")) {
  136.     if (argc>4) {
  137.         x=4;
  138.         if (!strcmp(argv[4],"PRIVATE")) {
  139.             private=1;
  140.             x=5;
  141.         }
  142.         goto StartHere;
  143.     }
  144.   }
  145.   if (!strcmp(argv[1],"-K")) {
  146.     if(argc>4) {
  147.         x=4;
  148.         goto StartHere;
  149.     }
  150.   }
  151.   mainarg=toupper(argv[1][1]);
  152.   goto DoIt;
  153.  
  154.  
  155. BadArgs:
  156.  
  157.     if (argc>1) {
  158.         fprintf(stderr,"\n\x7 Error in command line: `");
  159.         for (x=1;x<argc;x++) {
  160.             fprintf(stderr,"%s ",argv[x]);
  161.         }
  162.         fprintf(stderr,"'\n");
  163.     }
  164.     fprintf(stderr,"\nUsages:\n"
  165.             "\nXMSG -A<actionfile> Performs commands listed in <actionfile>"
  166.             "\nXMSG -P [LoBd#] [HiBd#] (options) Packs out deleted messages"
  167.             "\nXMSG -T [LoBd#] [HiBd#] [#mess] (options) Trim to specified #"
  168.             "\nXMSG -D [LoBd#] [HiBd#] [#days] (options) Delete older than # days"
  169.             "\nXMSG -R [LoBd#] [HiBd#] (PRIVATE) (options) Deletes received messages"
  170.             "\nXMSG -K [LoBd#] [HiBd#] (options) Kills junk msgs by (option) criteria"
  171.             "\n\nNote: when passing an argument, like the F option below, that requires"
  172.             "\ntwo words as one argument, use quotes to surround both the option and"
  173.             "\nits following argument, like XMSG -K 30 30 \"FHector Plasmic\"\n"
  174.             "\n[Any Key]: ");
  175.     getch();
  176.     fprintf(stderr,"\r\x1b[K"
  177.             "\n Options (separated by a space if more than one used):\n"
  178.             "B (delete backups)\n"
  179.             "V (verify deleted messages present before packing)\n"
  180.             "M<Drive:\\Path\\> (alternate message base path)\n"
  181.             "N<#LMRs> (Number of LMR pointers (must match w/ HeadEdit.CFG))\n"
  182.             "D (don't pack this pass--Valid for -T, -K and -D)\n"
  183.             "H<buffer> (if board(s) exceed this number, packing will take place to [#mess])\n"
  184.             "F<fromname> (-Kill Junk criterion)\n"
  185.             "T<toname> (-Kill Junk criterion)\n"
  186.             "S<subject> (-Kill Junk criterion)\n"
  187.             "P (partial subject match causes Junk to be -Killed)\n"
  188.             "! (provide verbose info)\n"
  189.             "C<#bytes> (compress while packing if msg>#bytes)\n"
  190.             "U (uncompress while packing)\n"
  191.             "A (any match (F, T or S) causes Junk to be -Killed)\n"
  192.             "\nActionfile lines are command lines without the leading - on the first argument.\n"
  193.             "There should be one 'command line' per line terminated by cr/lf.\n"
  194.             "Lines beginning with ; are comments.\n"
  195.             "\nXMSG is sensitive to the order of its arguments.\n");
  196.     exit(2);
  197.  
  198. StartHere:
  199.  
  200.     mainarg=toupper(argv[1][1]);
  201.     if(toupper(argv[1][1])=='A') {
  202.         numdays=0;
  203.         trimto=0;
  204.         private=0;
  205.         if(!fgets(il,256,fp)) {
  206.             fclose(fp);
  207.             fprintf(stderr,"\nXMSG Action file complete.\n");
  208.             exit(0);
  209.         }
  210.         il[255]=0;
  211.         strcpy(templine,stripcr(il));
  212.         if(il[strlen(il)-1]=='\n') il[strlen(il)-1]=0;
  213.         if(*il==0 || *il==';') goto StartHere;
  214.         p=strtok(il," ");
  215.         x=0;
  216.         while(p) {
  217.             strcpy(argarray[x],strupr(p));
  218.             *argarray[x+1]=0;
  219.             x++;
  220.             p=strtok(0," ");
  221.         }
  222.         argc=x;
  223.         mainarg=toupper(*argarray[0]);
  224.         number1=(word)atol(argarray[1]);
  225.         number2=(word)atol(argarray[2]);
  226.           if (mainarg=='K') {
  227.             if(argc>3) {
  228.                 x=3;
  229.                 goto ParseOpts;
  230.             }
  231.           }
  232.           if (mainarg=='P') {
  233.             if (argc>3) {
  234.                 x=3;
  235.                 goto ParseOpts;
  236.             }
  237.           }
  238.           if (mainarg=='D') {
  239.             if (argc<4) goto BadLine;
  240.             numdays=(word)atol(argarray[3]);
  241.             if (!numdays) goto BadLine;
  242.             if (argc>4) {
  243.                 x=4;
  244.                 goto ParseOpts;
  245.             }
  246.           }
  247.           if (mainarg=='T') {
  248.             if (argc<4) goto BadLine;
  249.             trimto=(word)atol(argarray[3]);
  250.             if (!trimto) goto BadLine;
  251.             if (argc>4) {
  252.                 x=4;
  253.                 goto ParseOpts;
  254.             }
  255.           }
  256.           if (mainarg=='R') {
  257.             if (argc>3) {
  258.                 x=3;
  259.                 if (!strcmp(argarray[3],"PRIVATE")) {
  260.                     private++;
  261.                     x=4;
  262.                 }
  263.                 goto ParseOpts;
  264.             }
  265.           }
  266. BadLine:
  267.         fprintf(stderr,"\nUnknown action line %s\n",il);
  268.         goto StartHere;
  269.     }
  270.     else {
  271.         strcpy(argarray[0],&argv[1][1]);
  272.         for(y=1;y<argc;y++) {
  273.             strcpy(argarray[y],argv[y+1]);
  274.         }
  275.         argc--;
  276.         x--;
  277.     }
  278.  
  279. ParseOpts:
  280.         killbackups=0;
  281.         dontanalyze=1;
  282.         dontpack=0;
  283.         buffer=0;
  284.         *fromname=0;
  285.         *toname=0;
  286.         *subj=0;
  287.         partial=0;
  288.         matchany=0;
  289.         compress_size=0;
  290.         uncompress=0;
  291.         for (;x<argc;x++) {
  292.             switch ((int)toupper(*argarray[x])) {
  293.                 case 'C':    compress_size=(word)atol(&argarray[x][1]);
  294.                             if(compress_size<1024)compress_size=1024;
  295.                             uncompress=0;
  296.                             break;
  297.                 case 'U':    uncompress=1;
  298.                             compress_size=0;
  299.                             break;
  300.                 case 'B':    killbackups=1;
  301.                             break;
  302.                 case 'V':    dontanalyze=0;
  303.                             break;
  304.                 case 'M':   strncpy(messpath,&argarray[x][1],79);
  305.                             messpath[79]=0;
  306.                             if(messpath[strlen(messpath)-1]!='\\') strcat(messpath,"\\");
  307.                             break;
  308.                 case 'N':   if(lastarray==NULL) {
  309.                                 conf.nolmrs=(word)atol(&argarray[x][1]);
  310.                                 lastarray=(unsigned int huge*)malloc(conf.nolmrs * sizeof(word));
  311.                                 if (lastarray==NULL) {
  312.                                     if(!conf.nolmrs) fprintf(stderr,"\nGotta have some LMRs\n");
  313.                                     else fprintf(stderr,"\nOOM for LMRs\n");
  314.                                     exit(1);
  315.                                 }
  316.                             }
  317.                             else {
  318.                                 fprintf(stderr,"\n\x1b[0;2;31m Respecification of # LMRs ignored\n"
  319.                                        "Rerun with separate action file/command line to respecify\n"
  320.                                        "Note: CONFIG.BBS setting always overrides if present.\n");
  321.                             }
  322.                             break;
  323.                 case 'D':    dontpack=1;
  324.                             break;
  325.                 case 'H':   buffer=(word)atol(&argarray[x][1]);
  326.                             break;
  327.                 case 'F':    strncpy(fromname,&argarray[x][1],36);
  328.                             fromname[35]=0;
  329.                             break;
  330.                 case 'T':    strncpy(toname,&argarray[x][1],36);
  331.                             toname[35]=0;
  332.                             break;
  333.                 case 'S':    strncpy(subj,&argarray[x][1],64);
  334.                             subj[63]=0;
  335.                             break;
  336.                 case 'P':    partial=1;
  337.                             break;
  338.                 case 'A':    matchany=1;
  339.                             break;
  340.                 case '!':    verbose=1;
  341.                             break;
  342.                 default:    fprintf(stderr,"\n\x7Never heard of `%s'\n",argarray[x]);
  343.                             break;
  344.             }
  345.         }
  346.  
  347.   if(uncompress && !dontpack) {
  348.     printf("\n\x1b[0;1;31m Uncompressing msgs...");
  349.   }
  350.   if (compress_size && !dontpack) {
  351.     printf("\n\x1b[0;1;31m Compressing msgs of %u bytes or larger...",compress_size);
  352.   }
  353.   if (killbackups)
  354.     printf("\n\x1b[0;1;31m Killing backups...");
  355.   if (!dontanalyze)
  356.     printf("\n\x1b[0;1;36m Checking for deleted messages before packing...");
  357.   if(dontpack) {
  358.     if(mainarg=='K' || mainarg=='T' || mainarg=='D') printf("\n\x1b[0;1;36m Not packing this pass...");
  359.     else fprintf(stderr,"\n\x1b[0;2;31mD(on't pack) not valid for -%c...ignored...",mainarg);
  360.   }
  361.   if((*fromname || *toname || *subj) && mainarg!='K') {
  362.     fprintf(stderr,"\n\x1b[0;2;31mJunk killing fields not valid for -%c...ignored...",mainarg);
  363.   }
  364.   if(mainarg=='K' && (!*fromname && !*toname && !subj)) {
  365.     fprintf(stderr,"\n\x1b[0;1;31mNo junk fields to check...");
  366.     goto StartHere;
  367.   }
  368.   if(buffer) {
  369.     if(mainarg=='T') printf("\n\x1b[0;1;36m Won't trim if under %u msgs...",buffer);
  370.     else fprintf(stderr,"\n\x1b[0;2;31mH not valid for -%c...ignored...",mainarg);
  371.   }
  372.  
  373.   if(verbose && *templine) printf("\nAction line: `%s'\n",templine);
  374.  
  375.   if(*messpath && conf.nolmrs) goto DoIt;
  376.   else {
  377.     fprintf(stderr,"\n\nYou must pass M and N options if you don't have a valid\n"
  378.            "XBBS CONFIG.BBS in the default directory!\n\n");
  379.     if(toupper(argv[1][1])!='A') goto BadArgs;
  380.     goto StartHere;
  381.   }
  382.  
  383. DoIt:
  384.  
  385.   if (number2<number1) {
  386.     fprintf(stderr,"\nHi/low conflict: High area %u, low area %u\n",number1,number2);
  387.     if(toupper(argv[1][1])!='A') goto BadArgs;
  388.     goto StartHere;
  389.   }
  390.  
  391.     switch ((int)mainarg) {
  392.         case 'P':   printf("\nPacking boards #%u to %u...\n",number1,number2);
  393.                     for (x=number1;x<number2+1;x++) {
  394.                         domsg(x, 0, 0);
  395.                         if (didbreak) break;
  396.                     }
  397.                     break;
  398.         case 'D':   printf("\nDeleting messages in boards #%u to %u older than %u days...\n",number1,number2,numdays);
  399.                     for (x=number1;x<number2+1;x++) {
  400.                         days(x, numdays);
  401.                         if (didbreak) break;
  402.                     }
  403.                     break;
  404.         case 'T':   printf("\nTrimming boards #%u to %u to %u messages...\n",number1,number2,trimto);
  405.                     for (x=number1;x<number2+1;x++) {
  406.                         if(buffer) {
  407.  
  408.                           char filename[133];
  409.  
  410.                           sprintf(filename,"%sXDATA.%03x",messpath,x);
  411.                           if(!findfirst(filename,&f,0)) {
  412.                               if ((word)(f.ff_fsize/(long)sizeof(struct _xmsg))<buffer) {
  413.                                 printf("\r\x1b[KSkipping #%u this time (%u msgs)\n",x,(word)(f.ff_fsize/(long)sizeof(struct _xmsg)));
  414.                                 continue;
  415.                               }
  416.                           }
  417.                         }
  418.                         trim(x, trimto);
  419.                         if (didbreak) break;
  420.                     }
  421.                     break;
  422.         case 'R':   if (private) strcpy(tempstring,"PRIVATE");
  423.                     else strcpy(tempstring,"");
  424.                     printf("\nPacking out received %s messages in boards #%u to %u...\n",tempstring,number1,number2);
  425.                     for (x=number1;x<number2+1;x++) {
  426.                         domsg(x,1,private);
  427.                         if (didbreak) break;
  428.                     }
  429.                     break;
  430.         case 'K':   printf("\nKilling junk messages in boards #%u to %u",number1,number2);
  431.                     if(verbose) printf("\n From: `%s'\nTo: `%s'\nSubj: `%s'",fromname,toname,subj);
  432.                     for(x=number1;x<number2+1;x++) {
  433.                         kill_junk(number1);
  434.                         if(didbreak) break;
  435.                     }
  436.                     break;
  437.     }
  438.     if (didbreak) {
  439.         fprintf(stderr,"\nStopping in response to user break.\n");
  440.         fclose(fp);
  441.         exit(0);
  442.     }
  443.     printf("\n");
  444.  
  445.     if(toupper(argv[1][1])!='A') {
  446.         fclose(fp);
  447.         exit(0);
  448.     }
  449.     goto StartHere;
  450. }
  451.  
  452.  
  453. void cdecl deinit (void) {
  454.  
  455.     fcloseall();
  456.     free_bufs();
  457. }
  458.  
  459.  
  460. int cdecl breakhandler (void) {
  461.  
  462.    didbreak=1;
  463.    fprintf(stderr,"\nOk, I'll stop as soon as it's safe.  Please wait...\n");
  464.    return 1;
  465.  
  466. }
  467.  
  468.  
  469. void pascal trim (word number1,word number2) {
  470.  
  471.  word register x;
  472.  char newfile[124];
  473.  struct _xmsg msg;
  474.  FILE *nf;
  475.  ulong sizefile;
  476.  struct date dos_date;
  477.  struct ffblk ft;
  478.  char atleastone=0;
  479.  long pos;
  480.  
  481.   sprintf(newfile,"%sXDATA.%03x",messpath,number1);
  482.  
  483.   if (checkfile(newfile)!=0) {
  484.     printf("\r\x1b[KNo messages in board #%u.",number1);
  485.     return;
  486.   }
  487.   sizefile=f.ff_fsize;
  488.  
  489.   if(!(nf=fopen(newfile,"r+b"))) {
  490.     fprintf(stderr,"\n\x1b[0;1;31mUnable to open message base.\x1b[0;2;37m\n");
  491.     return;
  492.   }
  493.   if ((word)(sizefile/(long)sizeof(struct _xmsg))<=number2) {
  494.      printf("\r\x1b[K%u message(s) in board #%u...trimming unnecessary.",(word)(sizefile/sizeof(msg)),number1);
  495.      fclose(nf);
  496.      return;
  497.   }
  498.   set_buf(nf,0);
  499.   printf("\r\x1b[KTrimming...");
  500.  
  501.   x=0;
  502.   while (x<((word)((sizefile/(long)sizeof(struct _xmsg))-(long)number2))) {
  503.  
  504.    int temp;
  505.  
  506.    pos=ftell(nf);
  507.    fseek(nf,0L,SEEK_CUR);
  508.    temp=fread (&msg,(int)sizeof(struct _xmsg),1,nf);
  509.    if (ferror(nf) || temp!=1) {
  510.     perror("");
  511.     break;
  512.    }
  513.    if (!(msg.m_attr & MSGKEEP)) {
  514.         msg.m_attr=(msg.m_attr | ((word)MSGDELETED));
  515.         atleastone=1;
  516.         fseek(nf,pos,SEEK_SET);
  517.         fwrite(&msg,sizeof(struct _xmsg),1,nf);
  518.    }
  519.    x++;
  520.   }
  521.   fclose(nf);
  522.   free_buf(0);
  523.   if(atleastone) {
  524.       dontanalyze=1;
  525.       if(!dontpack)domsg(number1,0,0);
  526.   }
  527.   else printf("\r\x1b[KMsgs marked KEEP circumvent trimming...");
  528. }
  529.  
  530.  
  531. void pascal kill_junk (word number1) {
  532.  
  533.  word register x;
  534.  char newfile[124];
  535.  struct _xmsg msg;
  536.  FILE *nf;
  537.  ulong sizefile;
  538.  struct date dos_date;
  539.  struct ffblk ft;
  540.  char atleastone=0;
  541.  long pos;
  542.  word hit=0;
  543.  word miss=0;
  544.  
  545.   sprintf(newfile,"%sXDATA.%03x",messpath,number1);
  546.  
  547.   if (checkfile(newfile)!=0) {
  548.     printf("\r\x1b[KNo messages in board #%u.",number1);
  549.     return;
  550.   }
  551.   sizefile=f.ff_fsize;
  552.  
  553.   if(!(nf=fopen(newfile,"r+b"))) {
  554.     fprintf(stderr,"\n\x1b[0;1;31mUnable to open message base.\x1b[0;2;37m\n");
  555.     return;
  556.   }
  557.   printf("\r\x1b[KKilling junk...");
  558.   set_buf(nf,0);
  559.  
  560.   rewind(nf);
  561.   x=0;
  562.   while (x<((word)((sizefile/(long)sizeof(struct _xmsg))))) {
  563.  
  564.    int temp;
  565.  
  566.    pos=ftell(nf);
  567.    fseek(nf,0L,SEEK_CUR);
  568.    temp=fread (&msg,(int)sizeof(struct _xmsg),1,nf);
  569.    if (ferror(nf) || temp!=1) {
  570.     perror("");
  571.     break;
  572.    }
  573.  
  574.    hit=miss=0;
  575.    if(*fromname) {
  576.     if(!stricmp(fromname,msg.from)) hit++;
  577.     else miss++;
  578.    }
  579.    if(*toname) {
  580.     if(!stricmp(toname,msg.to)) hit++;
  581.     else miss++;
  582.    }
  583.    if(*subj) {
  584.     if(!partial) {
  585.         if(!stricmp(subj,msg.subj)) hit++;
  586.         else miss++;
  587.     }
  588.     else {
  589.         if(!stristr(msg.subj,subj)) hit++;
  590.         else miss++;
  591.     }
  592.    }
  593.  
  594.    if((matchany && hit) || !miss) {
  595.        if (!(msg.m_attr & MSGKEEP)) {
  596.             msg.m_attr=(msg.m_attr | ((word)MSGDELETED));
  597.             atleastone=1;
  598.             fseek(nf,pos,SEEK_SET);
  599.             fwrite(&msg,sizeof(struct _xmsg),1,nf);
  600.             if(verbose) {
  601.                 printf("\n Kill: #%u\nFrom: `%s'\nTo: `%s'\nSubj: `%s'",msg.from,msg.to,msg.subj);
  602.             }
  603.        }
  604.    }
  605.  
  606.    x++;
  607.   }
  608.  
  609.   fclose(nf);
  610.   free_buf(0);
  611.   if(atleastone) {
  612.       dontanalyze=1;
  613.       if(!dontpack)domsg(number1,0,0);
  614.   }
  615. }
  616.  
  617.  
  618.  
  619. void pascal days (word number1,word number2) {
  620.  
  621.  word register x;
  622.  char newfile[124];
  623.  struct _xmsg msg;
  624.  FILE *nf;
  625.  ulong sizefile;
  626.  struct date dos_date;
  627.  struct ffblk ft;
  628.  char gotone=0;
  629.  long pos;
  630.  
  631.   sprintf(newfile,"%sXDATA.%03x",messpath,number1);
  632.  
  633.   if (checkfile(newfile)!=0) {
  634.     printf("\r\x1b[KNo messages in board #%u.",number1);
  635.     return;
  636.   }
  637.   sizefile=f.ff_fsize;
  638.  
  639.   if(!(nf=fopen(newfile,"r+b"))) {
  640.     fprintf(stderr,"\n\x1b[0;1;31mUnable to open message base.\x1b[0;2;37m\n");
  641.     fclose(nf);
  642.     return;
  643.   }
  644.   rewind(nf);
  645.   set_buf(nf,0);
  646.  
  647.   printf("\r\x1b[KPurging...");
  648.  
  649.   for(x=0;x<(word)(sizefile/(long)sizeof(struct _xmsg));x++) {
  650.  
  651.    int temp;
  652.  
  653.    pos=ftell(nf);
  654.    fseek(nf,0L,SEEK_CUR);
  655.    temp=fread (&msg,sizeof(struct _xmsg),1,nf);
  656.    if (ferror(nf) || temp!=1) {
  657.     perror("");
  658.     break;
  659.    }
  660.    dos_date.da_year=(int)msg.indate[0]+1989;
  661.    dos_date.da_mon=(int)msg.indate[1];
  662.    dos_date.da_day=(int)msg.indate[2];
  663.    if ((word)diffdays(&dos_date)>number2) {
  664.        if (!(msg.m_attr & MSGKEEP)) {
  665.            msg.m_attr=(msg.m_attr | ((word)MSGDELETED));
  666.            fseek(nf,pos,SEEK_SET);
  667.            fwrite(&msg,sizeof(struct _xmsg),1,nf);
  668.            gotone=1;
  669.        }
  670.    }
  671.   }
  672.  
  673.   fclose(nf);
  674.   free_buf(0);
  675.   dontanalyze=1;
  676.   if (gotone) {
  677.     if(!dontpack) domsg(number1,0,0);
  678.   }
  679.   else printf("\r\x1b[KDidn't find any old ones...");
  680.  
  681. }
  682.  
  683.  
  684.  
  685. void pascal domsg (number,received,private)
  686.  
  687. word number;
  688. char received;
  689. char private;
  690.  
  691. {
  692.  
  693.  word register x;
  694.  char buffer[133];
  695.  char textname[129];
  696.  char filename[129];
  697.  char newtext[129];
  698.  char newfile[129];
  699.  char msgname[129];
  700.  char noback=0;
  701.  char packit=0;
  702.  word lastlast;
  703.  struct _xmsg msg;
  704.  word wassize;
  705.  word huge *lastread;
  706.  word huge *holdlast;
  707.  FILE *fp;
  708.  FILE *pf;
  709.  FILE *nf;
  710.  FILE *fn;
  711.  FILE *us;
  712.  word register z;
  713.  char *message;
  714.  ulong sizefile;
  715.  struct date dos_date;
  716.  struct ffblk ft;
  717.  long pos;
  718.  ulong laststart,isstart;    /* Used to prevent carbons from expanding */
  719.  word lastlen,islen;        /* the msg text for each header */
  720.  struct dfree drivefree;
  721.  
  722.   isstart=laststart=0;
  723.   islen=lastlen=0;
  724.  
  725.   sprintf(filename,"%sXDBAK.%03x",messpath,number);
  726.   sprintf(textname,"%sXTBAK.%03x",messpath,number);
  727.   sprintf(newfile,"%sXDATA.%03x",messpath,number);
  728.   sprintf(newtext,"%sXTEXT.%03x",messpath,number);
  729.  
  730.   if (findfirst(newfile,&f,0)) {
  731.     printf("\r\x1b[KNo messages in board #%u.",number);
  732.     return;
  733.   }
  734.  
  735.   unlink(filename); /* Get rid of backups before checking drive space */
  736.   unlink(textname);
  737.  
  738.   getdfree((toupper(*messpath)-'@'),&drivefree);
  739.   if (((long)drivefree.df_avail*((long)drivefree.df_bsec*(long)drivefree.df_sclus)) < f.ff_fsize) {
  740.      printf("\nNot enough free drive space to safely pack area #%u.\n",number);
  741.      return;
  742.   }
  743.  
  744.   sizefile=f.ff_fsize/(long)sizeof(struct _xmsg);
  745.   wassize=(word)sizefile;
  746.  
  747.  if (!dontanalyze) {
  748.  
  749.   if(!(nf=fopen(newfile,"rb"))) {
  750.     fprintf(stderr,"\n\x1b[0;1;31mUnable to open message base.\x1b[0;2;37m\n");
  751.     return;
  752.   }
  753.  
  754.     if(verbose) {
  755.         printf("\nArea %u contains %u messages before packing.\n",number,sizefile);
  756.     }
  757.  
  758.       set_buf(nf,0);
  759.       printf("\r\x1b[KAnalyzing #%u...",number);
  760.       rewind(nf);
  761.       for(x=0;x<(word)sizefile;x++) {
  762.         fread (&msg,sizeof(struct _xmsg),1,nf);
  763.         if ((msg.m_attr & MSGDELETED)!=0) {
  764.             packit++;
  765.             break;
  766.         }
  767.         if (msg.m_attr & MSGKEEP) continue;
  768.         if (((msg.attr & MSGREAD) && received && !private) || (((msg.attr & MSGPRIVATE) && private && received && (msg.attr & MSGREAD)))) {
  769.             packit++;
  770.             break;
  771.         }
  772.       }
  773.       fclose(nf);
  774.       free_buf(0);
  775.  
  776.       if (!packit) {
  777.         printf("\r\x1b[K#%u doesn't need packing.",number);
  778.         return;
  779.       }
  780.    }
  781.  
  782.   remove(filename);
  783.   remove(textname);
  784.   rename(newfile,filename);
  785.   rename(newtext,textname);
  786.  
  787.  if(!(fp=fopen(filename,"rb"))) {
  788.     fprintf(stderr,"\n\x1b[0;1;31mUnable to open message base.\x1b[0;2;37m\n");
  789.     return;
  790.  }
  791.  if(!(pf=fopen(textname,"rb"))) {
  792.    fprintf(stderr,"\n\x1b[0;1;31mUnable to open message file.\x1b[0;2;37m\n");
  793.    fclose(fp);
  794.    return;
  795.  }
  796.  if(!(nf=fopen(newfile,"ab"))) {
  797.     fprintf(stderr,"\n\x1b[0;1;31mUnable to open message base.\x1b[0;2;37m\n");
  798.     fclose(fp);
  799.     fclose(pf);
  800.     return;
  801.  }
  802.  if(!(fn=fopen(newtext,"ab"))) {
  803.    fprintf(stderr,"\n\x1b[0;1;31mUnable to open message file.\x1b[0;2;37m\n");
  804.    fclose(fp);
  805.    fclose(pf);
  806.    fclose(nf);
  807.    return;
  808.  }
  809.  
  810.  holdlast=(word huge *)farmalloc((long)(sizeof(word)*(word)sizefile+1L));
  811.  if (holdlast==NULL) {
  812.     fprintf(stderr,"\nOut of memory.\n");
  813.     exit(3);
  814.  }
  815.  lastread=holdlast;
  816.  
  817.  printf("\r\x1b[K%u message(s) in board #%u.  Packing...",(word)sizefile,number);
  818.  
  819.  set_buf(fp,0);
  820.  set_buf(pf,1);
  821.  set_buf(nf,2);
  822.  set_buf(fn,3);
  823.  for(x=0;x<(word)sizefile;x++) {
  824.     fread (&msg,sizeof(struct _xmsg),1,fp);
  825.     if (!(msg.m_attr & MSGKEEP)) if (((msg.attr & MSGREAD) && received && !private) || (((msg.attr & MSGPRIVATE) && private && received && (msg.attr & MSGREAD)))) continue;
  826.     if(!msg.length)continue;
  827.     if ((msg.m_attr & MSGDELETED)==0) {
  828.         if(msg.length!=lastlen || msg.start!=laststart) {
  829.             laststart=msg.start;
  830.             lastlen=msg.length;
  831.             message=calloc(msg.length+1,sizeof(char));
  832.             if (message==NULL) {
  833.                fprintf(stderr,"\nAllocation error...aborting...\n");
  834.                exit(2);
  835.             }
  836.  
  837.             fseek(pf,msg.start,SEEK_SET);
  838.             fread(message,msg.length,1,pf);
  839.             msg.start=ftell(fn);
  840.  
  841.             if(!(msg.m_attr & MSGTREATED) && !(msg.m_attr & MSGPACKED)) {
  842.  
  843.                 char *tempo;
  844.  
  845.                 tempo=message;
  846.                 while (*tempo) {    /* Strip linefeeds and soft cr's FAST */
  847.                     if(*tempo=='\x8d' || *tempo=='\n') {
  848.                         if(*tempo=='\n')
  849.                             memmove(tempo,&tempo[1],msg.length-((word)tempo-(word)message));
  850.                         else {
  851.                             if(*(tempo-1)==' ' && tempo>message)
  852.                                 memmove(tempo,&tempo[1],msg.length-((word)tempo-(word)message));
  853.                             else *tempo=' ';
  854.                         }
  855.                     }
  856.                     tempo++;
  857.                 }
  858.                 msg.m_attr = (msg.m_attr | MSGTREATED);        /* Reads quicker */
  859.             }
  860.  
  861.             if(compress_size) {
  862.                 if(!(msg.m_attr & MSGPACKED) && (strlen(message)>compress_size)) {
  863.  
  864.                     char *tempo;
  865.  
  866.                     tempo=message;
  867.                     if(msg.length>65100) {
  868.                         msg.length=65100;
  869.                         message[65099]=0;
  870.                         msg.attr = msg.attr | MSGORPHAN;
  871.                     }
  872.                     message=pack_msg(message,&msg);
  873.                     if(!message) {
  874.                         message=tempo;
  875.                         msg.attr = msg.attr | MSGORPHAN;
  876.                     }
  877.                     else {
  878.                         free(tempo);
  879.                         msg.m_attr = msg.m_attr | MSGPACKED;
  880.                     }
  881.                 }
  882.             }
  883.             else if(uncompress) {
  884.                 if(msg.m_attr & MSGPACKED) {
  885.                     message=unpack_msg(&message);
  886.                     if(message==NULL) {
  887.                         message=calloc(msg.length+1,sizeof(char));
  888.                         if (message==NULL) {
  889.                            fprintf(stderr,"\nAllocation error...aborting...\n");
  890.                            exit(2);
  891.                         }
  892.                         fseek(pf,msg.start,SEEK_SET);
  893.                         fread(message,msg.length,1,pf);
  894.                         msg.start=ftell(fn);
  895.                         msg.attr = msg.attr | MSGORPHAN;
  896.                     }
  897.                     else {
  898.                         msg.length=strlen(message)+1;
  899.                         msg.m_attr = msg.m_attr & (~MSGPACKED);
  900.                     }
  901.                 }
  902.             }
  903.  
  904.             if(message) {
  905.                 fwrite(message,msg.length,1,fn);
  906.                 free(message);
  907.             }
  908.             islen=msg.length;
  909.             isstart=msg.start;
  910.         }
  911.         else {
  912.             msg.length=islen;
  913.             msg.start=isstart;
  914.         }
  915.         fwrite(&msg,sizeof(struct _xmsg),1,nf);
  916.         *lastread=x+1;
  917.         lastread++;
  918.     }
  919.     if (feof(fp)!=0) break;
  920.  }
  921.  
  922.  if (!noback) for (x=0;x<10;x++) printf(BACKSPACE);
  923.  else printf("\r\x1b[K");
  924.  
  925.  *lastread=0;
  926.  
  927.  fclose(nf);
  928.  free_buf(2);
  929.  
  930.  if(findfirst(newfile,&f,0)) sizefile=0;
  931.  else sizefile=f.ff_fsize/(long)sizeof(struct _xmsg);
  932.  
  933.  lastread=holdlast;
  934.  
  935.      if (number<(conf.nolmrs+1) && (word)sizefile<wassize) {
  936.        printf("\r\x1b[KAdjusting Last Message Pointers...     ");
  937.        sprintf(buffer,"%sLASTREAD.BBS",messpath);
  938.        if(findfirst(buffer,&ft,0)) {
  939.             fprintf(stderr,"\nCan't find %s\n",buffer);
  940.        }
  941.        else {
  942.            if ((us=fopen(buffer,"r+b"))==NULL) {
  943.                 printf("\nUnable to open %s\n",buffer);
  944.            }
  945.            else {
  946.              rewind(us);
  947.              set_buf(us,4);
  948.              for (x=0;x<(word)(ft.ff_fsize/(long)(conf.nolmrs*sizeof(word)));x++) {
  949.                     printf("\b\b\b\b\b%-5u",x+1);
  950.                     lastread=holdlast;
  951.                     z=(word)sizefile;
  952.                     pos=ftell(us);
  953.                     if(fseek(us,0L,SEEK_CUR)) perror("SEEK1");
  954.                     if(feof(us)) {
  955.                         fprintf(stderr,"\nLMR mismatch USERS.BBS -> LASTREAD.BBS\nRun XUSER and pack your User Database\n");
  956.                         break;
  957.                     }
  958.                     if (fread ((void *)lastarray,(conf.nolmrs * sizeof(word)),1,us)!=1) {
  959.                         perror("READ");
  960.                         continue;
  961.                     }
  962.                     if (!lastarray[number-1]) continue;
  963.                     if (!sizefile) {
  964.                         lastarray[number-1]=0;
  965.                         if (fseek(us,(long)pos,SEEK_SET)) perror("SEEK2");
  966.                         if (fwrite((void *)lastarray,(conf.nolmrs * sizeof(word)),1,us)!=1) perror("WRITE");
  967.                     }
  968.                     else if(lastarray[number-1]>wassize) {
  969.                         lastarray[number-1]=(word)sizefile;
  970.                         if (fseek(us,(long)pos,SEEK_SET)) perror("SEEK2");
  971.                         if (fwrite((void *)lastarray,(conf.nolmrs * sizeof(word)),1,us)!=1) perror("WRITE");
  972.                     }
  973.                     else {
  974.                         lastlast=lastarray[number-1];
  975.                         while(z) {
  976.                             if (lastread[z]<=lastarray[number-1] && lastread[z]!=0) {
  977.                                 lastarray[number-1]=(z+1);
  978.                                 break;
  979.                             }
  980.                             z--;
  981.                         }
  982.                         if(!z) lastarray[number-1]=0;
  983.                         if(lastarray[number-1]!=lastlast) {
  984.                             if (fseek(us,(long)pos,SEEK_SET)) perror("SEEK2");
  985.                             if (fwrite((void *)lastarray,(conf.nolmrs * sizeof(word)),1,us)!=1) perror("WRITE");
  986.                         }
  987.                     }
  988.             }
  989.        }
  990.        printf("\r\x1b[K");
  991.        fclose(us);
  992.        free_buf(4);
  993.      }
  994.  }
  995.  
  996. Alldone:
  997.  
  998.  fclose(fp);
  999.  fclose(pf);
  1000.  fclose(fn);
  1001.  free_buf(0);
  1002.  free_buf(1);
  1003.  free_buf(3);
  1004.  
  1005.  if (findfirst(newfile,&f,0)) f.ff_fsize=0;
  1006.  printf("\r\x1b[K%u message(s) in board #%u after packing.",(word)(f.ff_fsize/sizeof(msg)),number);
  1007.  if (killbackups!=0) {
  1008.    remove(filename);
  1009.    remove(textname);
  1010.  }
  1011.  if(verbose) printf("\n");
  1012.  if (f.ff_fsize==0) {
  1013.    printf("\r\x1b[K Deleting empty message base.");
  1014.    remove(newfile);
  1015.    remove(newtext);
  1016.  }
  1017.  farfree((word far *)holdlast);
  1018.  
  1019. }
  1020.  
  1021.  
  1022.  
  1023. int pascal checkfile (char *a) {
  1024.  
  1025.  return(findfirst(a,&f,0));
  1026.  
  1027. }
  1028.  
  1029.  
  1030. void pascal readconfig (void) {
  1031.  
  1032. FILE *fp;
  1033. struct ffblk f;
  1034.  
  1035.     if(findfirst("config.bbs",&f,0)) {
  1036.       fprintf(stderr,"\n'CONFIG.BBS' not found\n");
  1037.       return;
  1038.     }
  1039.     if(!(fp=fopen("config.bbs","rb"))) {
  1040.        perror("\nCONFIG.BBS ERROR");
  1041.        exit(2);
  1042.     }
  1043.     rewind(fp);
  1044.     fread(&conf,sizeof(conf),1,fp);
  1045.        fclose(fp);
  1046. }
  1047.  
  1048.  
  1049.  
  1050. ulong pascal diffdays (struct date *then) {    /* Duh...but seems to work */
  1051.  
  1052.   ulong numdays=0;
  1053.   ulong today=0;
  1054.   int register x;
  1055.   struct date dos_date;
  1056.   char month[13]={
  1057.     0,31,28,31,30,31,30,31,31,30,31,30,31
  1058.   };
  1059.  
  1060.   getdate(&dos_date);
  1061.   for (x=1987;x<dos_date.da_year;x++) numdays=numdays+365;
  1062.   for (x=1;x<dos_date.da_mon;x++) numdays=numdays+month[x];
  1063.   today=numdays+dos_date.da_day;
  1064.   numdays=0;
  1065.   for (x=1987;x<then->da_year;x++) numdays=numdays+365;
  1066.   for (x=1;x<then->da_mon;x++) numdays=numdays+month[x];
  1067.   numdays=numdays+then->da_day;
  1068.   return (today-numdays);
  1069.  
  1070. }
  1071.  
  1072.  
  1073. char * pascal stristr (char *t, char *s) {
  1074.  
  1075.    char *t1;
  1076.    char *s1;
  1077.  
  1078.    while(*t) {
  1079.       t1=t;
  1080.       s1=s;
  1081.       while(*s1) {
  1082.          if (toupper(*s1)!=toupper(*t)) break;
  1083.          else {
  1084.             s1++;
  1085.             t++;
  1086.          }
  1087.       }
  1088.       if (!*s1) return t1;
  1089.       t=t1+1;
  1090.    }
  1091.    return NULL;
  1092. }
  1093.  
  1094.  
  1095. char * pascal stripcr (char *a) {
  1096.  
  1097.   register int x;
  1098.  
  1099.   x=strlen(a);
  1100.   while (x && (a[x-1]=='\n' || a[x-1]=='\r')) a[--x]=0;
  1101.   return a;
  1102.  
  1103. }
  1104.  
  1105.  
  1106.  
  1107. char * pascal rstrip (char *a) {
  1108.  
  1109.   register int x;
  1110.  
  1111.   x=strlen(a);
  1112.   while (x && a && a[x-1]==' ') a[--x]=0;
  1113.   return a;
  1114. }
  1115.  
  1116.  
  1117.  
  1118. char * pascal lstrip (char *a) {
  1119.  
  1120.   register int x;
  1121.  
  1122.   x=strlen(a);
  1123.   while (x && *a==' ') memmove (a,(a+1),x--);
  1124.   return (a);
  1125. }
  1126.  
  1127.  
  1128. /* Tried this stuff, but it didn't seem to increase speed. */
  1129.  
  1130.  
  1131. int pascal set_buf (FILE *fp,char bufnum) {
  1132.  
  1133.  
  1134. /*
  1135.     if(bufnum>NUMBUFS-1) return 2;
  1136.     free_buf(bufnum);
  1137.     buf[bufnum]=(char *)malloc(MYBUFSIZE);
  1138.     if(!buf[bufnum]) return 1;
  1139.     if(setvbuf((FILE *)fp,(char *)buf[bufnum],(int)_IOFBF,(size_t)MYBUFSIZE)) printf("\nBuffer failure.\n");
  1140. */
  1141.     return 0;
  1142. }
  1143.  
  1144.  
  1145. int pascal free_bufs () {
  1146.  
  1147.     return 0;
  1148. /*
  1149.  
  1150.     char register x;
  1151.  
  1152.     for(x=0;x<NUMBUFS;x++) {
  1153.         free_buf(x);
  1154.     }
  1155.     return 0;
  1156. */
  1157. }
  1158.  
  1159. int pascal free_buf (char bufnum) {
  1160.  
  1161.  
  1162. /*
  1163.     if(bufnum>NUMBUFS-1) return 1;
  1164.     if(buf[bufnum]) {
  1165.         free(buf[bufnum]);
  1166.         buf[bufnum]=NULL;
  1167.     }
  1168. */
  1169.     return 0;
  1170. }
  1171.