home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / WWIV2.ZIP / FIX.C < prev    next >
C/C++ Source or Header  |  1992-12-03  |  32KB  |  1,383 lines

  1. /*****************************************************************************
  2.  
  3.                 WWIV Version 4
  4.                     Copyright (C) 1988-1993 by Wayne Bell
  5.  
  6. Distribution of the source code for WWIV, in any form, modified or unmodified,
  7. without PRIOR, WRITTEN APPROVAL by the author, is expressly prohibited.
  8. Distribution of compiled versions of WWIV is limited to copies compiled BY
  9. THE AUTHOR.  Distribution of any copies of WWIV not compiled by the author
  10. is expressly prohibited.
  11.  
  12.  
  13. *****************************************************************************/
  14.  
  15.  
  16.  
  17. /*
  18.  * Possible future enhancements:
  19.  *
  20.  * duplicate users?
  21.  * modem stuff ok
  22.  * check for various .dat files existence
  23.  * decrement mail waiting
  24.  */
  25.  
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <io.h>
  30. #include <sys\stat.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include <fcntl.h>
  34. #include <alloc.h>
  35. #define EXTENDED
  36. #include "vardec.h"
  37.  
  38.  
  39. #define OK  "   "
  40. #define NOK "## "
  41. #define QOK "?? "
  42.  
  43. int userfile=-1,configfile=-1,statusfile=-1;
  44. statusrec status;
  45. configrec syscfg;
  46. char *thisuser;
  47. char *thisuser_inact;
  48. char cdir[81];
  49. int num_dirs=0,num_subs=0;
  50. directoryrec *directories;
  51. subboardrec *subboards;
  52. unsigned long max_qscan;
  53. int sub_screwed[64];
  54. int curlsub=-1,bchanged,nummsgs;
  55. postrec *msgs;
  56. messagerec *postm[64],*emailm;
  57. char *emailmmm;
  58. int numpostm[64],numemailm,num_type_0;
  59. short gat[2048];
  60. int gat_section;
  61. int url;
  62.  
  63. smalrec *smallist,*new_smallist;
  64. int cur_users;
  65.  
  66.  
  67. int allow_changes=1,force_changes=0;
  68.  
  69. /****************************************************************************/
  70.  
  71. void read_user(unsigned int un)
  72. {
  73.   long pos;
  74.   char s[80];
  75.  
  76.   if (userfile==-1) {
  77.     sprintf(s,"%sUSER.LST",syscfg.datadir);
  78.     userfile=open(s,O_RDWR | O_BINARY);
  79.     if (userfile<0) {
  80.       *thisuser_inact=inact_deleted;
  81.       return;
  82.     }
  83.   }
  84.  
  85.   pos=((long) url) * ((long) un);
  86.   if (filelength(userfile)<(pos+syscfg.userreclen)) {
  87.     *thisuser_inact=inact_deleted;
  88.     return;
  89.   }
  90.  
  91.   lseek(userfile,pos,SEEK_SET);
  92.   read(userfile, thisuser, syscfg.userreclen);
  93. }
  94.  
  95. /****************************************************************************/
  96.  
  97. void write_user(unsigned int un)
  98. {
  99.   long pos;
  100.   char s[80];
  101.  
  102.   if (userfile==-1) {
  103.     sprintf(s,"%sUSER.LST",syscfg.datadir);
  104.     userfile=open(s,O_RDWR | O_BINARY);
  105.     if (userfile<0) {
  106.       return;
  107.     }
  108.   }
  109.  
  110.   pos=((long) url) * ((long) un);
  111.   if (filelength(userfile)<(pos+syscfg.userreclen)) {
  112.     return;
  113.   }
  114.  
  115.   lseek(userfile,pos,SEEK_SET);
  116.   write(userfile, thisuser, syscfg.userreclen);
  117. }
  118.  
  119. /****************************************************************************/
  120.  
  121.  
  122. void close_user(void)
  123. {
  124.   if (userfile!=-1) {
  125.     close(userfile);
  126.     userfile=-1;
  127.   }
  128. }
  129.  
  130. /****************************************************************************/
  131.  
  132. void save_status(void)
  133. {
  134.   char s[80];
  135.  
  136.   sprintf(s,"%sSTATUS.DAT",syscfg.datadir);
  137.   statusfile=open(s,O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
  138.   write(statusfile, (void *)(&status), sizeof(statusrec));
  139.   close(statusfile);
  140.   statusfile=-1;
  141. }
  142.  
  143. /****************************************************************************/
  144.  
  145. int exist(char *s)
  146. {
  147.   int f;
  148.  
  149.   f=open(s,O_RDONLY | O_BINARY);
  150.   close(f);
  151.   if (f>0)
  152.     return(1);
  153.   else
  154.     return(0);
  155. }
  156.  
  157. /****************************************************************************/
  158.  
  159. void give_up(void)
  160. {
  161.   printf("\n%sGiving up.\n",NOK);
  162.   exit(-1);
  163. }
  164.  
  165.  
  166. /****************************************************************************/
  167.  
  168. void oom(void *x)
  169. {
  170.   if (!x) {
  171.     printf("%sOut of memory.\n",NOK);
  172.     give_up();
  173.   }
  174. }
  175.  
  176. /****************************************************************************/
  177.  
  178. int yn(void)
  179. {
  180.   char ch;
  181.  
  182.   while (1) {
  183.     ch=getch();
  184.     if ((ch=='Y') || (ch=='y')) {
  185.       printf("Yes\n");
  186.       return(1);
  187.     }
  188.     if ((ch=='N') || (ch=='n') || (ch==13)) {
  189.       printf("No\n");
  190.       return(0);
  191.     }
  192.   }
  193. }
  194.  
  195.  
  196. /****************************************************************************/
  197.  
  198. void maybe_give_up(void)
  199. {
  200.   printf("%sFuture expansion might try to fix this problem.\n",OK);
  201.   give_up();
  202. }
  203.  
  204. /****************************************************************************/
  205.  
  206.  
  207. int cdto(char *s)
  208. {
  209.   char s1[81];
  210.   int i,db,st;
  211.  
  212.   strcpy(s1,s);
  213.   i=strlen(s1)-1;
  214.   db=(s1[i]=='\\');
  215.   if (i==0)
  216.     db=0;
  217.   if ((i==2) && (s1[1]==':'))
  218.     db=0;
  219.   if (db)
  220.     s1[i]=0;
  221.   st=chdir(s1);
  222.   if (s[1]==':') {
  223.     i=setdisk(s[0]-'A');
  224.     if (i<=(s[0]-'A'))
  225.       st=1;
  226.   }
  227.   return(st);
  228. }
  229.  
  230. /****************************************************************************/
  231.  
  232.  
  233. void get_dir(char *s, int be)
  234. {
  235.   strcpy(s,"X:\\");
  236.   s[0]='A'+getdisk();
  237.   getcurdir(0,&(s[3]));
  238.   if (be) {
  239.     if (s[strlen(s)-1]!='\\')
  240.       strcat(s,"\\");
  241.   }
  242. }
  243.  
  244.  
  245. /****************************************************************************/
  246.  
  247. int check_dir(char *dir, char *descr)
  248. {
  249.   int st;
  250.  
  251.   st=cdto(dir);
  252.   if (st)
  253.     printf("%sUnable to find dir '%s' for %s dir.\n",NOK,dir,descr);
  254.  
  255.   cdto(cdir);
  256.   return(st);
  257. }
  258.  
  259.  
  260. /****************************************************************************/
  261.  
  262.  
  263. void check_all_dirs(void)
  264. {
  265.   int st=0,st1;
  266.   int i;
  267.  
  268.   st |= check_dir(syscfg.msgsdir,"Messages");
  269.   st |= check_dir(syscfg.gfilesdir,"G-files");
  270.   st |= check_dir(syscfg.datadir,"Data");
  271.   st |= check_dir(syscfg.dloadsdir,"Default Dloads");
  272.   st |= check_dir(syscfg.tempdir,"Temp");
  273.  
  274.   if (st) {
  275.     printf("%sOne of the critical system directories is not present or not set correctly.\n",NOK);
  276.     give_up();
  277.   }
  278.  
  279.   for (i=0; i<num_dirs; i++) {
  280.     st1 = check_dir(directories[i].path,directories[i].name);
  281.     if (st1) {
  282.       st=1;
  283.       printf("%sEither create the dir, or use //DIREDIT to set it correctly.\n",NOK);
  284.       printf("%sThis program cannot fix this problem.\n",NOK);
  285.     }
  286.   }
  287. }
  288.  
  289.  
  290.  
  291. /****************************************************************************/
  292.  
  293. int trashed_str(char *s, int ml, int lower)
  294. {
  295.   int i,i1,st=0;
  296.  
  297.   i1=strlen(s);
  298.   if (i1>ml)
  299.     st=1;
  300.   else
  301.     for (i=0; i<i1; i++) {
  302.       if (s[i]<32)
  303.         st=1;
  304.       if ((!lower) && (islower(s[i])))
  305.         st=1;
  306.     }
  307.   return(st);
  308. }
  309.  
  310. /****************************************************************************/
  311.  
  312.  
  313. int trashed_user()
  314. {
  315.   if (trashed_str(thisuser,30,0))
  316.     return(1);
  317.  
  318.   return(0);
  319. }
  320.  
  321. void fix_user()
  322. {
  323.   thisuser[30]=0;
  324. }
  325.  
  326.  
  327. /****************************************************************************/
  328.  
  329.  
  330. void check_userlist(void)
  331. {
  332.   long l;
  333.   int nu,check_trash=0,trashed_userlist=0,xxx;
  334.  
  335.   url=syscfg.userreclen;
  336.   if (!url) {
  337.     url=700;
  338.     syscfg.userreclen=700;
  339.   }
  340.  
  341.   read_user(1);
  342.   if (userfile<0) {
  343.     printf("%sNo userlist present.\n",NOK);
  344.     give_up();
  345.   }
  346.  
  347.   l=filelength(userfile);
  348.   nu=(int) (l/((long)url)) - 1;
  349.  
  350.   printf("%sFound %d user records... ",OK,nu);
  351.  
  352.   if (nu>syscfg.maxusers) {
  353.     printf("Might be too many.\n");
  354.     check_trash=1;
  355.   } else
  356.     printf("Reasonable number.\n");
  357.  
  358.   if (check_trash) {
  359.     read_user(nu);
  360.     if ((xxx=trashed_user())!=0) {
  361.       trashed_userlist=1;
  362.       printf("%sUserrec #%u appeares trashed (%d).\n",NOK,nu,xxx);
  363.     }
  364.  
  365.     if (trashed_userlist) {
  366.       printf("%sUserlist appears screwed up.\n",NOK);
  367.     } else
  368.       printf("%sUserlist seems OK.\n",OK);
  369.   }
  370.  
  371.   if (trashed_userlist) {
  372.     if (!allow_changes)
  373.       give_up();
  374.  
  375.     printf("%sScanning for invalid user records...\n",OK);
  376.  
  377.     while ((nu) && (trashed_user()))
  378.       read_user(--nu);
  379.  
  380.     printf("%sAppears to be %u 'real' user records.\n",OK,nu);
  381.  
  382.     if (!force_changes) {
  383.       printf("%sTruncate userlist to %u users? ",QOK,nu);
  384.       if (!yn())
  385.         trashed_userlist=0;
  386.     }
  387.  
  388.     if (trashed_userlist) {
  389.       l=((long) nu) * ((long) syscfg.userreclen);
  390.       chsize(userfile,l);
  391.     }
  392.   }
  393. }
  394.  
  395.  
  396. /****************************************************************************/
  397.  
  398. void isr1(int un, char *name)
  399. {
  400.   int cp,i;
  401.   char s[81];
  402.   smalrec sr;
  403.  
  404.   cp=0;
  405.   while ((cp<cur_users) && (strcmp(name,(new_smallist[cp].name))>0))
  406.     ++cp;
  407.   memmove(&(new_smallist[cp+1]),&(new_smallist[cp]),sizeof(smalrec)*(cur_users-cp));
  408.   strcpy(sr.name,name);
  409.   sr.number=un;
  410.   new_smallist[cp]=sr;
  411.   ++cur_users;
  412. }
  413.  
  414. /****************************************************************************/
  415.  
  416.  
  417. void check_nameslist(void)
  418. {
  419.   char s[81];
  420.   int st=0,i,i1,xxx;
  421.   unsigned int status_users,names_users;
  422.  
  423.   printf("%sScanning NAMES.LST file...\n",OK);
  424.   sprintf(s,"%sNAMES.LST",syscfg.datadir);
  425.   i=open(s,O_RDONLY | O_BINARY);
  426.   if (i>0) {
  427.     if (filelength(i)) {
  428.       smallist=farmalloc(filelength(i));
  429.       oom(smallist);
  430.       read(i,smallist,(unsigned) filelength(i));
  431.       names_users=(unsigned int) (filelength(i)/sizeof(smalrec));
  432.       status_users=status.users;
  433.     } else
  434.       names_users=0;
  435.     close(i);
  436.  
  437.     if (names_users!=status_users) {
  438.       status.users=names_users;
  439.       printf("%sstatus.users was wrong.  ",NOK);
  440.       if (allow_changes) {
  441.         printf("Fixed it.\n");
  442.         save_status();
  443.       } else {
  444.         printf("Leaving it alone.\n");
  445.       }
  446.     }
  447.   } else {
  448.     names_users=0;
  449.     status.users=status.users;
  450.     printf("%s%s NOT FOUND.\n",NOK,s);
  451.   }
  452.  
  453.   cur_users=0;
  454.  
  455.   i1=filelength(userfile)/syscfg.userreclen-1;
  456.  
  457.   new_smallist=farmalloc(((long)i1) * ((long)sizeof(smalrec)));
  458.   oom(new_smallist);
  459.  
  460.   for (i=1; i<=i1; i++) {
  461.     read_user(i);
  462.     if ((*thisuser_inact & inact_deleted)==0) {
  463.       if ((xxx=trashed_user())!=0) {
  464.         printf("\n%s User #%d had trashed info (%d); patching.\n",NOK,i,xxx);
  465.         fix_user();
  466.         write_user(i);
  467.       }
  468.       isr1(i,thisuser);
  469.     }
  470.     if ((i % 10)==0)
  471.       printf("%s%d/%d\r",OK,i,i1);
  472.   }
  473.   printf("%s%d/%d\n",OK,i1,i1);
  474.  
  475.   if (cur_users!=names_users) {
  476.     st=1;
  477.     printf("%sA different number of users was found (%d vs %d).\n",NOK,
  478.         cur_users,names_users);
  479.  
  480.   } else {
  481.     for (i=0; i<names_users; i++) {
  482.       if (strcmp(smallist[i].name,new_smallist[i].name))
  483.         st=1;
  484.       if (smallist[i].number!=new_smallist[i].number)
  485.         st=1;
  486.     }
  487.   }
  488.   if (st) {
  489.     printf("%sThe new NAMES.LST file is different than the old one.\n",NOK);
  490.     if (allow_changes) {
  491.       status.users=cur_users;
  492.       i=open(s,O_RDWR | O_BINARY | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
  493.       if (i<0) {
  494.         printf("%sCouldn't create %s.\n",NOK,s);
  495.         give_up();
  496.       }
  497.       write(i,(void *) (new_smallist), (sizeof(smalrec) * status.users));
  498.       close(i);
  499.  
  500.       save_status();
  501.       printf("%sNAMES.LST file fixed.\n",OK);
  502.     } else {
  503.       printf("%sLeaving it alone, but it should be fixed.  There is nothing bad that can\n",NOK);
  504.       printf("%shappen by fixing the NAMES.LST file.\n",NOK);
  505.     }
  506.   }
  507. }
  508.  
  509. /****************************************************************************/
  510.  
  511. void iscan(int b)
  512. {
  513.   int f;
  514.   char s[81];
  515.  
  516.   curlsub=b;
  517.   bchanged=0;
  518.   nummsgs=0;
  519.   if (curlsub<0)
  520.     return;
  521.  
  522.   sprintf(s,"%s%s.SUB",syscfg.datadir,subboards[curlsub].filename);
  523.   f=open(s,O_BINARY | O_RDWR);
  524.   if (f==-1) {
  525.     f=open(s,O_BINARY | O_RDWR | O_CREAT,S_IREAD | S_IWRITE);
  526.     msgs[0].owneruser=0;
  527.     write(f,(void *) (&msgs[0]),sizeof(postrec));
  528.   }
  529.   lseek(f,0L,SEEK_SET);
  530.   nummsgs=(read(f,(void *) (&msgs[0]),255*sizeof(postrec)) / sizeof(postrec))-1;
  531.   nummsgs=msgs[0].owneruser;
  532.   close(f);
  533. }
  534.  
  535. /****************************************************************************/
  536.  
  537.  
  538. void savebase(void)
  539. {
  540.   int f;
  541.   char s[81];
  542.  
  543.   if (bchanged==0)
  544.     return;
  545.  
  546.   sprintf(s,"%s%s.SUB",syscfg.datadir,subboards[curlsub].filename);
  547.   f=open(s,O_BINARY | O_RDWR);
  548.   lseek(f,0L,SEEK_SET);
  549.   msgs[0].owneruser=nummsgs;
  550.   write(f,(void *) (&msgs[0]), ((nummsgs+1) * sizeof(postrec)));
  551.   close(f);
  552.   bchanged=0;
  553. }
  554.  
  555. /****************************************************************************/
  556.  
  557. #define GATSECLEN (4096L+2048L*512L)
  558. #define MSG_STARTING (((long)gat_section)*GATSECLEN + 4096)
  559.  
  560.  
  561. void set_gat_section(int f, int section)
  562. {
  563.   long l,l1;
  564.   int i;
  565.  
  566.   if (gat_section!=section) {
  567.     l=filelength(f);
  568.     l1=((long)section)*GATSECLEN;
  569.     if (l<l1) {
  570.       chsize(f,l1);
  571.       l=l1;
  572.     }
  573.     lseek(f,l1,SEEK_SET);
  574.     if (l<(l1+4096)) {
  575.       for (i=0; i<2048; i++)
  576.         gat[i]=0;
  577.       write(f,(void *)gat, 4096);
  578.     } else {
  579.       read(f,(void *)gat, 4096);
  580.     }
  581.     gat_section=section;
  582.   }
  583. }
  584.  
  585. /****************************************************************************/
  586.  
  587.  
  588. void save_gat(int f)
  589. {
  590.   long l;
  591.  
  592.   l=((long)gat_section)*GATSECLEN;
  593.   lseek(f,l,SEEK_SET);
  594.   write(f,(void *)gat,4096);
  595. }
  596.  
  597. /****************************************************************************/
  598.  
  599.  
  600.  
  601. void remove_link(messagerec *m1, char *aux)
  602. {
  603.   messagerec m;
  604.   char s[81],s1[81];
  605.   int f;
  606.   long csec,nsec;
  607.  
  608.   m=*m1;
  609.   strcpy(s,syscfg.msgsdir);
  610.   switch(m.storage_type) {
  611.     case 0:
  612.     case 1:
  613.       ltoa(m.stored_as,s1,16);
  614.       if (m.storage_type==1) {
  615.         strcat(s,aux);
  616.         strcat(s,"\\");
  617.       }
  618.       strcat(s,s1);
  619.       unlink(s);
  620.       break;
  621.     case 2:
  622.       f=open_file(aux);
  623.       set_gat_section(f,m.stored_as/2048);
  624.       csec=m.stored_as % 2048;
  625.       while ((csec>0) && (csec<2048)) {
  626.         nsec=(long) gat[csec];
  627.     gat[csec]=0;
  628.     csec=nsec;
  629.       }
  630.       save_gat(f);
  631.       close(f);
  632.       break;
  633.     default:
  634.       /* illegal storage type */
  635.       break;
  636.   }
  637. }
  638.  
  639. /****************************************************************************/
  640.  
  641. void deletem(int mn)
  642. {
  643.   int i;
  644.  
  645.   if ((mn>0) && (mn<=nummsgs)) {
  646.     remove_link(&(msgs[mn].msg),(subboards[curlsub].filename));
  647.     for (i=mn; i<nummsgs; i++)
  648.       msgs[i]=msgs[i+1];
  649.     nummsgs--;
  650.     bchanged=1;
  651.   }
  652. }
  653.  
  654.  
  655. /****************************************************************************/
  656.  
  657. void delmail(int f, int loc)
  658. {
  659.   mailrec m,m1;
  660.   userrec u;
  661.   int rm,i,t,otf;
  662.   char s[81];
  663.  
  664.   sprintf(s,"%sEMAIL.DAT",syscfg.datadir);
  665.   f=open(s,O_RDWR | O_BINARY);
  666.  
  667.  
  668.   lseek(f,((long) loc) * ((long) sizeof(mailrec)), SEEK_SET);
  669.   read(f,(void *)&m,sizeof(mailrec));
  670.  
  671.   rm=1;
  672.   if (m.status & status_multimail) {
  673.     t=filelength(f)/sizeof(mailrec);
  674.     otf=0;
  675.     for (i=0; i<t; i++)
  676.       if (i!=loc) {
  677.         lseek(f,((long)i)*((long)sizeof(mailrec)),SEEK_SET);
  678.         read(f,(void *)&m1,sizeof(mailrec));
  679.         if ((m.msg.stored_as==m1.msg.stored_as) && (m.msg.storage_type==m1.msg.storage_type) && (m1.daten!=0xffffffff))
  680.           otf=1;
  681.       }
  682.     if (otf)
  683.       rm=0;
  684.   }
  685.  
  686.   close(f);
  687.   if (rm)
  688.     remove_link(&m.msg,"EMAIL");
  689.  
  690.   if (m.tosys==0) {
  691. #ifdef DEC_MAIL_WAITING
  692.     read_user(m.touser,&u);
  693.     if (u.waiting) {
  694.       --u.waiting;
  695.       write_user(m.touser,&u);
  696.       close_user();
  697.     }
  698. #endif
  699.   }
  700.  
  701.   f=open(s,O_RDWR | O_BINARY);
  702.   lseek(f,((long) loc) * ((long) sizeof(mailrec)), SEEK_SET);
  703.   m.touser=0;
  704.   m.tosys=0;
  705.   m.daten=0xffffffff;
  706.   m.msg.storage_type=0;
  707.   m.msg.stored_as=0xffffffff;
  708.   write(f,(void *)&m,sizeof(mailrec));
  709.   close(f);
  710. }
  711.  
  712. /****************************************************************************/
  713.  
  714. void find_max_qscan(void)
  715. {
  716.   int i,cs,r,t,f,any_screwed;
  717.   unsigned long maxthissub;
  718.   mailrec m;
  719.   char s[81];
  720.  
  721.   for (i=0; i<64; i++)
  722.     sub_screwed[i]=0;
  723.   max_qscan=0L;
  724.   any_screwed=0;
  725.   num_type_0=0;
  726.  
  727.   printf("%sScanning subboards...\n",OK);
  728.  
  729.   for (cs=0; cs<num_subs; cs++) {
  730.     iscan(cs);
  731.     maxthissub=0L;
  732.     numpostm[cs]=nummsgs;
  733.     if (nummsgs) {
  734.       postm[cs]=farmalloc(nummsgs*sizeof(messagerec));
  735.       oom(postm[cs]);
  736.       for (i=1; i<=nummsgs; i++) {
  737.         postm[cs][i-1]=msgs[i].msg;
  738.         if (maxthissub>=msgs[i].qscan) {
  739.           sub_screwed[cs]=1;
  740.           any_screwed=1;
  741.         }
  742.         if (maxthissub<msgs[i].qscan)
  743.           maxthissub=msgs[i].qscan;
  744.         if (max_qscan<msgs[i].qscan)
  745.           max_qscan=msgs[i].qscan;
  746.         if (msgs[i].msg.storage_type<2) {
  747.           if (max_qscan<msgs[i].msg.stored_as)
  748.             max_qscan=msgs[i].msg.stored_as;
  749.           if (msgs[i].msg.storage_type==0)
  750.             ++num_type_0;
  751.         }
  752.       }
  753.       if (sub_screwed[cs]) {
  754.         printf("%sSub '%s' has q-scan pointers screwed up.\n",NOK,subboards[cs].name);
  755.       }
  756.     }
  757.   }
  758.  
  759.   printf("%sScanning EMAIL.DAT file...\n",OK);
  760.  
  761.   sprintf(s,"%sEMAIL.DAT",syscfg.datadir);
  762.   f=open(s,O_BINARY | O_RDWR);
  763.   if (f!=-1) {
  764.     t=(int) (filelength(f)/sizeof(mailrec));
  765.     r=0;
  766.     numemailm=t;
  767.     emailm=farmalloc(t*sizeof(messagerec));
  768.     emailmmm=farmalloc(t);
  769.     if (t) {
  770.       oom(emailm);
  771.       oom(emailmmm);
  772.     }
  773.     while (r<t) {
  774.       lseek(f,(long)(sizeof(mailrec)) * (long)(r),SEEK_SET);
  775.       read(f,(void *)&m,sizeof(mailrec));
  776.       emailm[r]=m.msg;
  777.       emailmmm[r]=m.status;
  778.       if ((m.tosys!=0) || (m.touser!=0)) {
  779.         if (m.msg.storage_type<2)
  780.           if (max_qscan<m.msg.stored_as)
  781.             max_qscan=m.msg.stored_as;
  782.         if (m.msg.storage_type==0)
  783.           ++num_type_0;
  784.       }
  785.       ++r;
  786.     }
  787.     close(f);
  788.   }
  789.  
  790.   max_qscan++;
  791.   if (max_qscan>status.qscanptr) {
  792.     printf("%sMax qscan pointer trashed (%ld vs %ld).\n",NOK,max_qscan,status.qscanptr);
  793.     status.qscanptr=max_qscan;
  794.     if (allow_changes) {
  795.       save_status();
  796.       printf("%sFixed.\n",OK);
  797.     } else
  798.       printf("%sLeaving as-is, but it should be fixed.\n",OK);
  799.   }
  800.  
  801.   if ((allow_changes) && (any_screwed)) {
  802.     if (!force_changes) {
  803.       printf("%sFix up q-scan pointers? ",QOK);
  804.       if (!yn())
  805.         any_screwed=0;
  806.     }
  807.     if (any_screwed) {
  808.       for (cs=0; cs<num_subs; cs++) {
  809.         if (sub_screwed[cs]) {
  810.           printf("%sResetting q-scan ptrs for '%s'\n",OK,subboards[cs].name);
  811.           iscan(cs);
  812.           for (i=1; i<=nummsgs; i++) {
  813.             msgs[i].qscan=status.qscanptr++;
  814.           }
  815.           bchanged=1;
  816.           savebase();
  817.         }
  818.       }
  819.       save_status();
  820.     }
  821.   }
  822. }
  823.  
  824.  
  825. /****************************************************************************/
  826.  
  827.  
  828. typedef struct {
  829.   long    stored_as;
  830.   int     subnum,msgnum;
  831. } type_0;
  832.  
  833.  
  834. /****************************************************************************/
  835.  
  836.  
  837. char *describem(char *s, int subnum, int msgnum)
  838. {
  839.   mailrec me;
  840.   postrec mp;
  841.   char s1[81];
  842.   int f;
  843.  
  844.   if (subnum==-1) { /* email */
  845.     sprintf(s1,"%sEMAIL.DAT",syscfg.datadir);
  846.     f=open(s1,O_BINARY | O_RDWR);
  847.     lseek(f,(long)(sizeof(mailrec)) * (long)(msgnum),SEEK_SET);
  848.     read(f,(void *)&me,sizeof(mailrec));
  849.     close(f);
  850.  
  851.     if (me.fromsys)
  852.       sprintf(s1,"user #%d @%d",me.fromuser,me.fromsys);
  853.     else
  854.       sprintf(s1,"user #%d",me.fromuser);
  855.  
  856.     sprintf(s,"Mail from %s to ",s1);
  857.  
  858.     if (me.tosys)
  859.       sprintf(s1,"user #%d @%d",me.touser,me.tosys);
  860.     else
  861.       sprintf(s1,"user #%d",me.touser);
  862.  
  863.     strcat(s,s1);
  864.  
  865.     sprintf(s1," '%.30s'",me.title);
  866.     strcat(s,s1);
  867.  
  868.   } else {
  869.     iscan(subnum);
  870.     mp=msgs[msgnum];
  871.     if (mp.ownersys)
  872.       sprintf(s,"Post #%d on '%s' by user #%d @%d",
  873.           msgnum+1,
  874.           subboards[subnum].name,
  875.           mp.owneruser,
  876.           mp.ownersys);
  877.     else
  878.       sprintf(s,"Post #%d on '%s' by user #%d",
  879.           msgnum+1,
  880.           subboards[subnum].name,
  881.           mp.owneruser);
  882.   }
  883.   return(s);
  884. }
  885.  
  886.  
  887. /****************************************************************************/
  888.  
  889.  
  890. void check_type_1(int num, messagerec *list, char *extra, int todesc)
  891. {
  892.   char s[81],s1[81];
  893.   int i,i1,dup,ex;
  894.   char *already_done;
  895.  
  896.   if (!num)
  897.     return;
  898.  
  899.   sprintf(s,"%s%s\\",syscfg.msgsdir,extra);
  900.   already_done=farmalloc(num);
  901.   oom(already_done);
  902.  
  903.   for (i=0; i<num; i++)
  904.     already_done[i]=0;
  905.  
  906.   for (i=0; i<num; i++)
  907.     if ((list[i].storage_type==1) && (!already_done[i])) {
  908.       sprintf(s1,"%s%lX",s,list[i].stored_as);
  909.       ex=exist(s1);
  910.       dup=0;
  911.       if (!((todesc==-1) && (emailmmm[i] & status_multimail))) {
  912.         for (i1=i+1; i1<num; i1++)
  913.           if (list[i1].storage_type==1)
  914.             if (list[i1].stored_as==list[i].stored_as)
  915.               dup=1;
  916.       }
  917.       if (dup || (!ex)) {
  918.         if (!ex)
  919.           printf("%sFile not found: '%s'\n",NOK,s1);
  920.         if (dup)
  921.           printf("%sMessage file multiply referenced: '%s'\n",NOK,s1);
  922.         printf("%s  for %s\n",NOK,describem(s1,todesc,i));
  923.  
  924.         for (i1=i+1; i1<num; i1++)
  925.           if ((list[i1].storage_type==1) &&
  926.               (list[i1].stored_as==list[i].stored_as)) {
  927.             printf("%s  for %s\n",NOK,describem(s1,todesc,i1));
  928.             already_done[i1]=1;
  929.           }
  930.         printf("%s  No action taken.\n\n",NOK);
  931.       }
  932.     }
  933.   farfree(already_done);
  934. }
  935.  
  936. /****************************************************************************/
  937.  
  938.  
  939. int open_file(char *fn)
  940. {
  941.   int f,i;
  942.   char s[81];
  943.  
  944.   sprintf(s,"%s%s.DAT",syscfg.msgsdir,fn);
  945.   f=open(s,O_RDWR | O_BINARY);
  946.   if (f<0)
  947.     return(-1);
  948.  
  949.   lseek(f,0L,SEEK_SET);
  950.   read(f,(void *)gat,4096);
  951.   gat_section=0;
  952.   return(f);
  953. }
  954.  
  955.  
  956. /****************************************************************************/
  957.  
  958.  
  959. void check_type_2(int num, messagerec *list, char *extra, int todesc)
  960. {
  961.   int f,i,i1,any,csec,csec1,any_dead,num_deadm,anything_done,numsec,high,sec;
  962.   char s[81];
  963.   int *deadm;
  964.   short *gati, *gatint;
  965.  
  966.   if (!num)
  967.     return;
  968.  
  969.   f=open_file(extra);
  970.   numsec=((int) (filelength(f)/GATSECLEN))+1;
  971.   high=numsec*2048;
  972.  
  973.   gati=farmalloc(high*2);
  974.   gatint=farmalloc(high*2);
  975.  
  976.  
  977.   for (i=0; i<high; i++)
  978.     gati[i]=0;
  979.  
  980.   for (i=0; i<numsec; i++) {
  981.     set_gat_section(f,i);
  982.     memcpy(gatint+2048*i, gat, 4096);
  983.   }
  984.  
  985.   deadm=farmalloc(num*2);
  986.   oom(deadm);
  987.  
  988.   any=0;
  989.   any_dead=0;
  990.   num_deadm=0;
  991.   anything_done=0;
  992.  
  993.   for (i=0; i<num; i++)
  994.     if (list[i].storage_type==2) {
  995.       if (f<0) {
  996.         if (!any) {
  997.           any=1;
  998.           printf("%sType 2 data file not found: '%s%s.DAT'\n",
  999.                 NOK,syscfg.msgsdir,extra);
  1000.         }
  1001.         deadm[num_deadm++]=i;
  1002.         anything_done=1;
  1003.       } else {
  1004.         sec=(list[i].stored_as/2048)*2048;
  1005.         csec=list[i].stored_as % 2048;
  1006.         while ((csec>0) && (csec<2048)) {
  1007.           if (gati[csec+sec]) {
  1008.             if (!((todesc==-1) && (emailmmm[i] & status_multimail))) {
  1009.               if (gati[csec+sec]!=-2)
  1010.                 gati[csec+sec]=-1;
  1011.               ++any_dead;
  1012.             }
  1013.             csec=-1;
  1014.           } else {
  1015.             if (!gatint[csec+sec]) {
  1016.               gati[csec+sec]=-2;
  1017.               ++any_dead;
  1018.               csec=-1;
  1019.             } else {
  1020.               gati[csec+sec]=i+1;
  1021.               csec=gatint[csec+sec];
  1022.             }
  1023.           }
  1024.         }
  1025.       }
  1026.     }
  1027.  
  1028.   if (f<0) {
  1029.     if (anything_done) {
  1030.  
  1031.       printf("%sDunno what to do about that.\n",NOK);
  1032.  
  1033.     }
  1034.     farfree(gati);
  1035.     farfree(deadm);
  1036.     farfree(gatint);
  1037.     close(f);
  1038.     return;
  1039.   }
  1040.  
  1041.   if (any_dead) {
  1042.     anything_done=1;
  1043.     printf("%sErrors in '%s%s.DAT':\n",NOK,syscfg.msgsdir,extra);
  1044.     for (i=0; i<num; i++)
  1045.       if (list[i].storage_type==2) {
  1046.         sec=(list[i].stored_as/2048)*2048;
  1047.         csec=list[i].stored_as % 2048;
  1048.         csec1=-1;
  1049.         while ((csec>0) && (csec<2048)) {
  1050.           if (gati[csec+sec]<0) {
  1051.             printf("%s  for %s\n",NOK,describem(s,todesc,i));
  1052.             if (gati[csec+sec]==-1) {
  1053.               printf("%s    Collided on cluster #%d\n",NOK,csec+sec);
  1054.               if (csec1==-1) {
  1055.                 printf("%s    First cluster of message, removing.\n",NOK);
  1056.                 deadm[num_deadm++]=i;
  1057.               } else {
  1058.                 gatint[csec1+sec]=-1;
  1059.                 printf("%s    Truncating message.\n",NOK);
  1060.               }
  1061.             } else if (gati[csec+sec]==-2) {
  1062.               printf("%s    Pointed to unallocated cluster #%d\n",NOK,csec+sec);
  1063.               if (csec1==-1) {
  1064.                 printf("%s    First cluster of message, removing.\n",NOK);
  1065.                 deadm[num_deadm++]=i;
  1066.               } else {
  1067.                 gatint[csec1+sec]=-1;
  1068.                 printf("%s    Truncating message.\n",NOK);
  1069.               }
  1070.             } else {
  1071.               printf("%s    Unknown error.\n",NOK);
  1072.             }
  1073.           }
  1074.           csec1=csec;
  1075.           csec=gatint[csec+sec];
  1076.         }
  1077.       }
  1078.  
  1079.   }
  1080.  
  1081.   any_dead=0;
  1082.   for (csec=0; csec<high; csec++)
  1083.     if ((gatint[csec]) && (gati[csec]<=0)) {
  1084.       gatint[csec]=0;
  1085.       ++any_dead;
  1086.     }
  1087.   if (any_dead) {
  1088.     printf("%sLost clusters recovered from '%s%s.DAT': %d\n",
  1089.           NOK,syscfg.msgsdir,extra,any_dead);
  1090.     anything_done=1;
  1091.   }
  1092.  
  1093.   if (anything_done) {
  1094.     i=force_changes;
  1095.     if ((allow_changes) && (!i)) {
  1096.       printf("%sWrite these changes to disk? ",QOK);
  1097.       i=yn();
  1098.     }
  1099.  
  1100.  
  1101.     if (i) {
  1102.       printf("%sUpdating '%s%s.DAT'.\n",OK,syscfg.msgsdir,extra);
  1103.       for (i=0; i<numsec; i++) {
  1104.         set_gat_section(f,i);
  1105.         memcpy(gat, gatint+2048*i, 4096);
  1106.         save_gat(f);
  1107.       }
  1108.       if (num_deadm) {
  1109.         printf("%sRemoving messages with no text.\n",OK);
  1110.         if (todesc!=-1) {
  1111.           iscan(todesc);
  1112.  
  1113.           for (i=0; i<num_deadm; i++)
  1114.             deletem(deadm[i]-i+1);
  1115.  
  1116.           savebase();
  1117.         } else {
  1118.           for (i=0; i<num_deadm; i++)
  1119.             delmail(f,deadm[i]);
  1120.  
  1121.         }
  1122.       }
  1123.     }
  1124.   }
  1125.   close(f);
  1126.   farfree(deadm);
  1127.   farfree(gati);
  1128.   farfree(gatint);
  1129. }
  1130.  
  1131.  
  1132. /****************************************************************************/
  1133.  
  1134.  
  1135. void check_msg_consistency(void)
  1136. {
  1137.   type_0 *x0;
  1138.   int cs,i,i1,i2,cp,ex;
  1139.   char s[81],s1[81];
  1140.  
  1141.   /* check type 0 consistency */
  1142.  
  1143.   if (num_type_0) {
  1144.     printf("%sChecking type 0 message consistency.\n",OK);
  1145.     x0=farmalloc(sizeof(type_0)*num_type_0);
  1146.     oom(x0);
  1147.     cp=0;
  1148.     for (cs=0; cs<num_subs; cs++)
  1149.       for (i=0; i<numpostm[cs]; i++)
  1150.         if ((!postm[cs][i].storage_type) && (postm[cs][i].stored_as != -1)) {
  1151.           x0[cp].stored_as=postm[cs][i].stored_as;
  1152.           x0[cp].subnum=cs;
  1153.           x0[cp].msgnum=i+1;
  1154.           ++cp;
  1155.         }
  1156.     for (cs=0; cs<numemailm; cs++)
  1157.       if ((!emailm[cs].storage_type) && (emailm[cs].stored_as != -1)) {
  1158.         x0[cp].stored_as=emailm[cs].stored_as;
  1159.         x0[cp].subnum=-1;
  1160.         x0[cp].msgnum=cs;
  1161.         ++cp;
  1162.       }
  1163.  
  1164.     for (i=0; i<cp; i++) {
  1165.       if (x0[i].subnum!=-2) {
  1166.         sprintf(s,"%s%lX",syscfg.msgsdir,x0[i].stored_as);
  1167.         ex=exist(s);
  1168.  
  1169.         i2=0;
  1170.  
  1171.         for (i1=i+1; i1<cp; i1++)
  1172.           if (x0[i].stored_as==x0[i1].stored_as)
  1173.             i2=1;
  1174.  
  1175.         if (i2 || (!ex)) {
  1176.           if (!ex)
  1177.             printf("%sFile not found: '%s'\n",NOK,s);
  1178.           if (i2)
  1179.             printf("%sMessage file multiply referenced: '%s'\n",NOK,s);
  1180.           printf("%s  for %s\n",NOK,describem(s1,x0[i].subnum,x0[i].msgnum));
  1181.           for (i1=i+1; i1<cp; i1++)
  1182.             if (x0[i].stored_as==x0[i1].stored_as) {
  1183.               printf("%s  for %s\n",NOK,describem(s1,x0[i1].subnum,x0[i1].msgnum));
  1184.               x0[i1].subnum=-2;
  1185.             }
  1186.           printf("%s  No action taken.\n\n",NOK);
  1187.         }
  1188.       }
  1189.     }
  1190.  
  1191.     farfree(x0);
  1192.   }
  1193.  
  1194.   /* check type 1 consistency */
  1195.  
  1196.   printf("%sChecking type 1 message consistency.\n",OK);
  1197.   check_type_1(numemailm,emailm,"EMAIL",-1);
  1198.   for (cs=0; cs<num_subs; cs++) {
  1199.     check_type_1(numpostm[cs],postm[cs],subboards[cs].filename,cs);
  1200.   }
  1201.  
  1202.  
  1203.   /* check type 2 consistency */
  1204.  
  1205.   printf("%sChecking type 2 message consistency.\n",OK);
  1206.   check_type_2(numemailm,emailm,"EMAIL",-1);
  1207.   for (cs=0; cs<num_subs; cs++) {
  1208.     check_type_2(numpostm[cs],postm[cs],subboards[cs].filename,cs);
  1209.   }
  1210. }
  1211.  
  1212.  
  1213. /****************************************************************************/
  1214.  
  1215.  
  1216. void ck_size(char *fn, int f, long rl)
  1217. {
  1218.   long l;
  1219.  
  1220.   l=filelength(f);
  1221.   if (l<rl) {
  1222.     printf("%s%s too short (%ld<%ld).\n",NOK,fn,l,rl);
  1223.     give_up();
  1224.   }
  1225.  
  1226.   if (l>rl) {
  1227.     printf("%s%s too long (%ld>%ld).\n",NOK,fn,l,rl);
  1228.     if (allow_changes)
  1229.       printf("%sAttempting to continue.\n",NOK);
  1230.     else
  1231.       give_up();
  1232.   }
  1233. }
  1234.  
  1235. /****************************************************************************/
  1236.  
  1237. void init(void)
  1238. {
  1239.   char s[81];
  1240.   int i;
  1241.  
  1242.   strcpy(s,"CONFIG.DAT");
  1243.   configfile=open(s,O_RDWR | O_BINARY);
  1244.   if (configfile<0) {
  1245.     printf("%s%s NOT FOUND.\n",NOK,s);
  1246.     give_up();
  1247.   }
  1248.  
  1249.   ck_size(s,configfile,sizeof(configrec));
  1250.  
  1251.   read(configfile,(void *) (&syscfg), sizeof(configrec));
  1252.   close(configfile);
  1253.  
  1254.   strcpy(cdir,"X:\\");
  1255.   cdir[0]='A'+getdisk();
  1256.   getcurdir(0,&(cdir[3]));
  1257.  
  1258.   if (check_dir(syscfg.datadir,"Data")) {
  1259.     printf("%sMust find data directory to continue.\n",NOK);
  1260.     give_up();
  1261.   }
  1262.  
  1263.   if (!syscfg.userreclen)
  1264.     syscfg.userreclen=700;
  1265.  
  1266.   thisuser=(char *)farmalloc(syscfg.userreclen);
  1267.   if (!thisuser) {
  1268.     printf("%sCould not allocate %d bytes for userrec.\n",NOK,syscfg.userreclen);
  1269.     give_up();
  1270.   }
  1271.   thisuser_inact=thisuser+syscfg.inactoffset;
  1272.  
  1273.   sprintf(s,"%sSTATUS.DAT",syscfg.datadir);
  1274.   statusfile=open(s,O_RDWR | O_BINARY);
  1275.   if (statusfile<0) {
  1276.     printf("%s%s NOT FOUND.\n",NOK,s);
  1277.     if (allow_changes) {
  1278.       printf("%sRe-creating STATUS.DAT file.\n",OK);
  1279.       strcpy(status.date1,"00/00/00");
  1280.       strcpy(status.date2,status.date1);
  1281.       strcpy(status.date3,status.date1);
  1282.       strcpy(status.log1,"000000.LOG");
  1283.       strcpy(status.log2,status.log1);
  1284.       strcpy(status.gfiledate,"00/00/00");
  1285.       status.users=0;
  1286.       status.callernum=65535;
  1287.       status.callstoday=0;
  1288.       status.msgposttoday=0;
  1289.       status.emailtoday=0;
  1290.       status.fbacktoday=0;
  1291.       status.uptoday=0;
  1292.       status.activetoday=0;
  1293.       status.qscanptr=0L;
  1294.       status.amsganon=0;
  1295.       status.amsguser=0;
  1296.       status.callernum1=0L;
  1297.       status.net_edit_stuff=0;
  1298.       status.wwiv_version=0;
  1299.       status.net_version=0;
  1300.       status.net_bias=0.001;
  1301.     } else
  1302.       give_up();
  1303.   } else {
  1304.     ck_size(s,statusfile,sizeof(statusrec));
  1305.     read(statusfile,(void *)(&status), sizeof(statusrec));
  1306.     close(statusfile);
  1307.   }
  1308.  
  1309.  
  1310.   sprintf(s,"%sDIRS.DAT",syscfg.datadir);
  1311.   i=open(s,O_RDWR | O_BINARY);
  1312.   if (i<0) {
  1313.     printf("%s%s NOT FOUND.\n",NOK,s);
  1314.     maybe_give_up();
  1315.   } else {
  1316.     directories=(directoryrec *)farmalloc(filelength(i));
  1317.     if (!directories) {
  1318.       printf("%sCouldn't allocate %ld bytes for %s.\n",NOK,filelength(i), s);
  1319.       give_up();
  1320.     }
  1321.     num_dirs=(read(i,directories, (filelength(i))))/
  1322.               sizeof(directoryrec);
  1323.     close(i);
  1324.   }
  1325.  
  1326.   sprintf(s,"%sSUBS.DAT",syscfg.datadir);
  1327.   i=open(s,O_RDWR | O_BINARY);
  1328.   if (i<0) {
  1329.     printf("%s%s NOT FOUND.\n",NOK,s);
  1330.     maybe_give_up();
  1331.   } else {
  1332.     subboards=(subboardrec *)farmalloc(filelength(i));
  1333.     if (!subboards) {
  1334.       printf("%sCouldn't allocate %ld bytes for %s.\n",NOK,filelength(i),s);
  1335.       give_up();
  1336.     }
  1337.     num_subs=(read(i, subboards, (filelength(i))))/
  1338.              sizeof(subboardrec);
  1339.     close(i);
  1340.   }
  1341.  
  1342.   msgs=farmalloc(255*sizeof(postrec));
  1343.   oom(msgs);
  1344. }
  1345.  
  1346. /****************************************************************************/
  1347.  
  1348.  
  1349. void main(int argc, char *argv[])
  1350. {
  1351.   int i;
  1352.   char *ss;
  1353.  
  1354.   for (i=1; i<argc; i++) {
  1355.     ss=argv[i];
  1356.     if ((*ss=='/') || (*ss=='-')) {
  1357.  
  1358.     } else {
  1359.       printf("%sUnknown argument: '%s'\n",NOK,ss);
  1360.     }
  1361.   }
  1362.  
  1363.   printf("\n");
  1364.   printf("Fix - Fix WWIV files.\n");
  1365.   printf("\n");
  1366.  
  1367.   if (getenv("BBS")) {
  1368.     printf("Fix should only be run OUTSIDE the BBS.\n");
  1369.     exit(-1);
  1370.   }
  1371.  
  1372.   init();
  1373.  
  1374.   check_all_dirs();
  1375.   check_userlist();
  1376.   check_nameslist();
  1377.   find_max_qscan();
  1378.   check_msg_consistency();
  1379.  
  1380. }
  1381.  
  1382.  
  1383.