home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / SMB / CHKSMB / CHKSMB.C next >
Encoding:
C/C++ Source or Header  |  1997-04-25  |  18.9 KB  |  673 lines

  1. /* CHKSMB.C */
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. #include <dos.h>
  6. #include "smblib.h"
  7.  
  8. /****************************************************************************/
  9. /* Checks the disk drive for the existence of a file. Returns 1 if it       */
  10. /* exists, 0 if it doesn't.                                                 */
  11. /* Called from upload                                                       */
  12. /****************************************************************************/
  13. char fexist(char *filespec)
  14. {
  15.     struct find_t f;
  16.  
  17. if(!_dos_findfirst(filespec,0,&f))
  18.     return(1);
  19. return(0);
  20. }
  21.  
  22. /****************************************************************************/
  23. /* Returns in 'string' a character representation of the number in l with   */
  24. /* commas.                                                                    */
  25. /****************************************************************************/
  26. char *ultoac(ulong l, char *string)
  27. {
  28.     char str[256];
  29.     signed char i,j,k;
  30.  
  31. ultoa(l,str,10);
  32. i=strlen(str)-1;
  33. j=i/3+1+i;
  34. string[j--]=0;
  35. for(k=1;i>-1;k++) {
  36.     string[j--]=str[i--];
  37.     if(j>0 && !(k%3))
  38.         string[j--]=','; }
  39. return(string);
  40. }
  41.  
  42. /****************************************************************************/
  43. /* Returns an ASCII string for FidoNet address 'addr'                       */
  44. /****************************************************************************/
  45. char *faddrtoa(fidoaddr_t addr)
  46. {
  47.     static char str[25];
  48.     char point[25];
  49.  
  50. sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
  51. if(addr.point) {
  52.     sprintf(point,".%u",addr.point);
  53.     strcat(str,point); }
  54. return(str);
  55. }
  56.  
  57. char *usage="\nusage: chksmb [/opts] <filespec.SHD>\n"
  58.             "\n"
  59.             " opts:\n"
  60.             "       s - stop after errored message base\n"
  61.             "       p - pause after errored messsage base\n"
  62.             "       q - quiet mode (no beeps while checking)\n"
  63.             "       a - don't check allocation files\n"
  64.             "       t - don't check translation strings\n"
  65.             "       e - display extended info on corrupted msgs\n";
  66.  
  67. int main(int argc, char **argv)
  68. {
  69.     char        str[128],*p,*s,*beep="\7";
  70.     int         i,j,x,y,lzh,errors,errlast,stop_on_error=0,pause_on_error=0
  71.                 ,chkxlat=1,chkalloc=1,lzhmsg,extinfo=0,msgerr;
  72.     ushort        xlat;
  73.     ulong        l,m,n,length,size,total=0,orphan=0,deleted=0,headers=0
  74.                 ,*offset,*number,xlaterr
  75.                 ,delhdrblocks,deldatblocks,hdrerr=0,lockerr=0,hdrnumerr=0
  76.                 ,acthdrblocks,actdatblocks
  77.                 ,dfieldlength=0,dfieldoffset=0
  78.                 ,dupenum=0,dupenumhdr=0,dupeoff=0,attr=0,actalloc=0
  79.                 ,datactalloc=0,misnumbered=0,timeerr=0,idxofferr=0,idxerr
  80.                 ,zeronum,idxzeronum,idxnumerr,packable=0L,totallzhsaved=0L
  81.                 ,totalmsgs=0,totallzhmsgs=0,totaldelmsgs=0,totalmsgbytes=0L
  82.                 ,lzhblocks,lzhsaved;
  83.     smb_t        smb;
  84.     idxrec_t    idx;
  85.     smbmsg_t    msg;
  86.  
  87. fprintf(stderr,"\nCHKSMB v2.00ß · Check Synchronet Message Base · "
  88.     "Devloped 1995-1997 Rob Swindell\n");
  89.  
  90. if(argc<2) {
  91.     printf("%s",usage);
  92.     exit(1); }
  93.  
  94. errlast=errors=0;
  95. for(x=1;x<argc;x++) {
  96.     if(stop_on_error && errors)
  97.         break;
  98.     if(pause_on_error && errlast!=errors) {
  99.         fprintf(stderr,"\7\nHit any key to continue...");
  100.         if(!getch())
  101.             getch();
  102.         printf("\n"); }
  103.     errlast=errors;
  104.     if(argv[x][0]=='/') {
  105.         for(y=1;argv[x][y];y++)
  106.             switch(toupper(argv[x][y])) {
  107.                 case 'Q':
  108.                     beep="";
  109.                     break;
  110.                 case 'P':
  111.                     pause_on_error=1;
  112.                     break;
  113.                 case 'S':
  114.                     stop_on_error=1;
  115.                     break;
  116.                 case 'T':
  117.                     chkxlat=0;
  118.                     break;
  119.                 case 'A':
  120.                     chkalloc=0;
  121.                     break;
  122.                 case 'E':
  123.                     extinfo=1;
  124.                     break;
  125.                 default:
  126.                     printf("%s",usage);
  127.                     exit(1); }
  128.         continue; }
  129.  
  130. strcpy(smb.file,argv[x]);
  131. p=strrchr(smb.file,'.');
  132. s=strrchr(smb.file,'\\');
  133. if(p>s) *p=0;
  134. strupr(smb.file);
  135.  
  136. sprintf(str,"%s.SHD",smb.file);
  137. if(!fexist(str)) {
  138.     printf("\n%s doesn't exist.\n",smb.file);
  139.     continue; }
  140.  
  141. fprintf(stderr,"\nChecking %s Headers\n\n",smb.file);
  142.  
  143. smb.retry_time=30;
  144. if((i=smb_open(&smb))!=0) {
  145.     printf("smb_open returned %d\n",i);
  146.     errors++;
  147.     continue; }
  148.  
  149. length=filelength(fileno(smb.shd_fp));
  150. if(length<sizeof(smbhdr_t)) {
  151.     printf("Empty\n");
  152.     smb_close(&smb);
  153.     continue; }
  154.  
  155. if((i=smb_locksmbhdr(&smb))!=0) {
  156.     smb_close(&smb);
  157.     printf("smb_locksmbhdr returned %d\n",i);
  158.     errors++;
  159.     continue; }
  160.  
  161. if((length/SHD_BLOCK_LEN)*sizeof(ulong)) {
  162.     if((number=(ulong *)MALLOC(((length/SHD_BLOCK_LEN)+2)*sizeof(ulong)))
  163.         ==NULL) {
  164.         printf("Error allocating %lu bytes of memory\n"
  165.             ,(length/SHD_BLOCK_LEN)*sizeof(ulong));
  166.         return(++errors); } }
  167. else
  168.     number=NULL;
  169.  
  170. if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
  171.     if((i=smb_open_ha(&smb))!=0) {
  172.         printf("smb_open_ha returned %d\n",i);
  173.         return(++errors); }
  174.  
  175.     if((i=smb_open_da(&smb))!=0) {
  176.         printf("smb_open_da returned %d\n",i);
  177.         return(++errors); } }
  178.  
  179. headers=deleted=orphan=dupenumhdr=attr=zeronum=timeerr=lockerr=hdrerr=0;
  180. actalloc=datactalloc=deldatblocks=delhdrblocks=xlaterr=0;
  181. lzhblocks=lzhsaved=acthdrblocks=actdatblocks=0;
  182.  
  183. for(l=smb.status.header_offset;l<length;l+=size) {
  184.     fprintf(stderr,"\r%2u%%  ",(long)(100.0/((float)length/l)));
  185.     msg.idx.offset=l;
  186.     msgerr=0;
  187.     if((i=smb_lockmsghdr(&smb,&msg))!=0) {
  188.         printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
  189.         lockerr++;
  190.         headers++;
  191.         size=SHD_BLOCK_LEN;
  192.         continue; }
  193.     if((i=smb_getmsghdr(&smb,&msg))!=0) {
  194.         smb_unlockmsghdr(&smb,&msg);
  195.         if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
  196.             fseek(smb.sha_fp
  197.                 ,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
  198.             j=fgetc(smb.sha_fp);
  199.             if(j) {             /* Allocated block or at EOF */
  200.                 printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i);
  201.                 hdrerr++; }
  202.             else
  203.                 delhdrblocks++; }
  204.         else {
  205.             /* printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i); */
  206.             delhdrblocks++; }
  207.         size=SHD_BLOCK_LEN;
  208.         continue; }
  209.     smb_unlockmsghdr(&smb,&msg);
  210.     fprintf(stderr,"#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from);
  211.  
  212.     lzhmsg=0;
  213.     if(msg.hdr.attr&MSG_DELETE) {
  214.         deleted++;
  215.         if(number)
  216.             number[headers]=0;
  217.         if(smb.status.attr&SMB_HYPERALLOC)
  218.             deldatblocks+=smb_datblocks(smb_getmsgdatlen(&msg)); }
  219.     else {
  220.         actdatblocks+=smb_datblocks(smb_getmsgdatlen(&msg));
  221.         if(msg.hdr.number>smb.status.last_msg) {
  222.             fprintf(stderr,"%sOut-Of-Range message number\n",beep);
  223.             msgerr=1;
  224.             if(extinfo)
  225.                 printf("MSGERR: Header number (%lu) greater than last (%lu)\n"
  226.                     ,msg.hdr.number,smb.status.last_msg);
  227.             hdrnumerr++; }
  228.  
  229.         if(smb_getmsgidx(&smb,&msg)) {
  230.             fprintf(stderr,"%sNot found in index\n",beep);
  231.             msgerr=1;
  232.             if(extinfo)
  233.                 printf("MSGERR: Header number (%lu) not found in index\n"
  234.                     ,msg.hdr.number);
  235.             orphan++; }
  236.         else if(msg.hdr.attr!=msg.idx.attr) {
  237.             fprintf(stderr,"%sAttributes mismatch index\n",beep);
  238.             msgerr=1;
  239.             if(extinfo)
  240.                 printf("MSGERR: Header attributes (%04X) do not match index "
  241.                     "attributes (%04X)\n"
  242.                     ,msg.hdr.attr,msg.idx.attr);
  243.             attr++; }
  244.         else if(msg.hdr.when_imported.time!=msg.idx.time) {
  245.             fprintf(stderr,"%sImport date/time mismatch index\n",beep);
  246.             msgerr=1;
  247.             if(extinfo)
  248.                 printf("MSGERR: Header import date/time does not match "
  249.                     "index import date/time\n");
  250.             timeerr++; }
  251.  
  252.         if(msg.hdr.number==0) {
  253.             fprintf(stderr,"%sZero message number\n",beep);
  254.             msgerr=1;
  255.             if(extinfo)
  256.                 printf("MSGERR: Header number is zero (invalid)\n");
  257.             zeronum++; }
  258.         if(number) {
  259.             for(m=0;m<headers;m++)
  260.                 if(number[m] && msg.hdr.number==number[m]) {
  261.                     fprintf(stderr,"%sDuplicate message number\n",beep);
  262.                     msgerr=1;
  263.                     if(extinfo)
  264.                         printf("MSGERR: Header number (%lu) duplicated\n"
  265.                             ,msg.hdr.number);
  266.                     dupenumhdr++;
  267.                     break; }
  268.             number[headers]=msg.hdr.number; }
  269.         if(chkxlat) {        /* Check translation strings */
  270.             for(i=0;i<msg.hdr.total_dfields;i++) {
  271.                 fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset,SEEK_SET);
  272.                 if(!fread(&xlat,2,1,smb.sdt_fp))
  273.                     xlat=0xffff;
  274.                 lzh=0;
  275.                 if(xlat==XLAT_LZH) {
  276.                     lzh=1;
  277.                     if(!fread(&xlat,2,1,smb.sdt_fp))
  278.                         xlat=0xffff; }
  279.                 if(xlat!=XLAT_NONE) {
  280.                     fprintf(stderr,"%sUnsupported Xlat %04X dfield[%u]\n"
  281.                         ,beep,xlat,i);
  282.                     msgerr=1;
  283.                     if(extinfo)
  284.                         printf("MSGERR: Unsupported translation type (%04X) "
  285.                             "in dfield[%u]\n"
  286.                             ,xlat,i);
  287.                     xlaterr++; }
  288.                 else {
  289.                     if(lzh) {
  290.                         lzhmsg=1;
  291.                         if(fread(&m,4,1,smb.sdt_fp)) { /* Get uncompressed len */
  292.                             lzhsaved+=(smb_datblocks(m+2)
  293.                                 -smb_datblocks(msg.dfield[i].length))
  294.                                 *SDT_BLOCK_LEN;
  295.                             lzhblocks+=smb_datblocks(msg.dfield[i].length);
  296.                         } } } } } }
  297.  
  298.     size=smb_getmsghdrlen(&msg);
  299.     while(size%SHD_BLOCK_LEN)
  300.         size++;
  301.  
  302.     if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
  303.         fseek(smb.sha_fp,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
  304.         for(m=0;m<size;m+=SHD_BLOCK_LEN) {
  305. /***
  306.             if(msg.hdr.attr&MSG_DELETE && (i=fgetc(smb.sha_fp))!=0) {
  307.                 fprintf(stderr,"%sDeleted Header Block %lu marked %02X\n"
  308.                     ,beep,m/SHD_BLOCK_LEN,i);
  309.                 msgerr=1;
  310.                 delalloc++; }
  311. ***/
  312.             if(!(msg.hdr.attr&MSG_DELETE) && (i=fgetc(smb.sha_fp))!=1) {
  313.                 fprintf(stderr,"%sActive Header Block %lu marked %02X\n"
  314.                     ,beep,m/SHD_BLOCK_LEN,i);
  315.                 msgerr=1;
  316.                 if(extinfo)
  317.                     printf("MSGERR: Active header block %lu marked %02X "
  318.                         "instead of 01\n"
  319.                         ,m/SHD_BLOCK_LEN,i);
  320.                 actalloc++; } }
  321.  
  322.         if(!(msg.hdr.attr&MSG_DELETE)) {
  323.             acthdrblocks+=(size/SHD_BLOCK_LEN);
  324.             for(n=0;n<msg.hdr.total_dfields;n++) {
  325.                 if(msg.dfield[n].offset&0x80000000UL) {
  326.                     msgerr=1;
  327.                     if(extinfo)
  328.                         printf("MSGERR: Invalid Data Field [%u] Offset: %lu\n"
  329.                             ,n,msg.dfield[n].offset);
  330.                     dfieldoffset++; }
  331.                 if(msg.dfield[n].length&0x80000000UL) {
  332.                     msgerr=1;
  333.                     if(extinfo)
  334.                         printf("MSGERR: Invalid Data Field [%u] Length: %lu\n"
  335.                             ,n,msg.dfield[n].length);
  336.                     dfieldlength++; }
  337.                 fseek(smb.sda_fp
  338.                     ,((msg.hdr.offset+msg.dfield[n].offset)/SDT_BLOCK_LEN)*2
  339.                     ,SEEK_SET);
  340.                 for(m=0;m<msg.dfield[n].length;m+=SDT_BLOCK_LEN) {
  341.                     if(!fread(&i,2,1,smb.sda_fp) || !i) {
  342.                         fprintf(stderr
  343.                             ,"%sActive Data Block %lu.%lu marked free\n"
  344.                             ,beep,n,m/SHD_BLOCK_LEN);
  345.                         msgerr=1;
  346.                         if(extinfo)
  347.                             printf("MSGERR: Active Data Block %lu.%lu "
  348.                                 "marked free\n"
  349.                                 ,n,m/SHD_BLOCK_LEN);
  350.                         datactalloc++; } } } }
  351.         else
  352.             delhdrblocks+=(size/SHD_BLOCK_LEN); }
  353.  
  354.     else {     /* Hyper Alloc */
  355.         if(msg.hdr.attr&MSG_DELETE)
  356.             delhdrblocks+=(size/SHD_BLOCK_LEN);
  357.         else
  358.             acthdrblocks+=(size/SHD_BLOCK_LEN); }
  359.  
  360.     totallzhmsgs+=lzhmsg;
  361.     headers++;
  362.     if(msgerr && extinfo) {
  363.         printf("\n");
  364.         printf("%-20s: %s\n","Message Base",smb.file);
  365.         printf("%-20s: %lu (%lu)\n","Message Number"
  366.             ,msg.hdr.number,msg.offset+1);
  367.         printf("%-20s: %s\n","Subject",msg.subj);
  368.         printf("%-20s: %s","To",msg.to);
  369.         if(msg.to_net.type)
  370.             printf(" (%s)",msg.to_net.type==NET_FIDO
  371.                 ? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
  372.         printf("\n%-20s: %s","From",msg.from);
  373.         if(msg.from_net.type)
  374.             printf(" (%s)",msg.from_net.type==NET_FIDO
  375.                 ? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
  376.                     : msg.from_net.addr);
  377.         printf("\n");
  378.         printf("%-20s: %.24s\n","When Written"
  379.             ,ctime((time_t *)&msg.hdr.when_written.time));
  380.         printf("%-20s: %.24s\n","When Imported"
  381.             ,ctime((time_t *)&msg.hdr.when_imported.time));
  382.         printf("%-20s: %04hXh\n","Type"
  383.             ,msg.hdr.type);
  384.         printf("%-20s: %04hXh\n","Version"
  385.             ,msg.hdr.version);
  386.         printf("%-20s: %u\n","Length"
  387.             ,msg.hdr.length);
  388.         printf("%-20s: %04hXh\n","Attributes"
  389.             ,msg.hdr.attr);
  390.         printf("%-20s: %08lXh\n","Auxilary Attributes"
  391.             ,msg.hdr.auxattr);
  392.         printf("%-20s: %08lXh\n","Network Attributes"
  393.             ,msg.hdr.netattr);
  394.         printf("%-20s: %06lXh\n","Header Offset"
  395.             ,msg.idx.offset);
  396.         printf("%-20s: %06lXh\n","Data Offset"
  397.             ,msg.hdr.offset);
  398.         printf("%-20s: %u\n","Total Data Fields"
  399.             ,msg.hdr.total_dfields);
  400.         printf("\n"); }
  401.  
  402.     smb_freemsgmem(&msg); }
  403.  
  404. if(number)
  405.     FREE(number);
  406.  
  407. fprintf(stderr,"\r%79s\r100%%\n","");
  408.  
  409.  
  410. if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
  411.  
  412.     fprintf(stderr,"\nChecking %s Data Blocks\n\n",smb.file);
  413.  
  414.     length=filelength(fileno(smb.sda_fp));
  415.  
  416.     fseek(smb.sda_fp,0L,SEEK_SET);
  417.     for(l=0;l<length;l+=2) {
  418.         fprintf(stderr,"\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
  419.         i=0;
  420.         if(!fread(&i,2,1,smb.sda_fp))
  421.             break;
  422.         if(!i)
  423.             deldatblocks++; }
  424.  
  425.     fclose(smb.sha_fp);
  426.     fclose(smb.sda_fp);
  427.  
  428.     fprintf(stderr,"\r%79s\r100%%\n",""); }
  429.  
  430. total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
  431.  
  432. dupenum=dupeoff=misnumbered=idxzeronum=idxnumerr=idxofferr=idxerr=0;
  433.  
  434. if(total) {
  435.  
  436. fprintf(stderr,"\nChecking %s Index\n\n",smb.file);
  437.  
  438. if((offset=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
  439.     printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
  440.     return(++errors); }
  441. if((number=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
  442.     printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
  443.     return(++errors); }
  444. fseek(smb.sid_fp,0L,SEEK_SET);
  445.  
  446. for(l=0;l<total;l++) {
  447.     fprintf(stderr,"\r%2lu%%  %5lu ",l ? (long)(100.0/((float)total/l)) : 0,l);
  448.     if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
  449.         break;
  450.     fprintf(stderr,"#%-5lu (%06lX) 1st Pass ",idx.number,idx.offset);
  451. /***
  452.     if(idx.attr&MSG_DELETE) {
  453.         fprintf(stderr,"%sMarked for deletion\n",beep);
  454.         delidx++; }
  455. ***/
  456.     for(m=0;m<l;m++)
  457.         if(number[m]==idx.number) {
  458.             fprintf(stderr,"%sDuplicate message number\n",beep);
  459.             dupenum++;
  460.             break; }
  461.     for(m=0;m<l;m++)
  462.         if(offset[m]==idx.offset) {
  463.             fprintf(stderr,"%sDuplicate offset\n",beep,idx.offset);
  464.             dupeoff++;
  465.             break; }
  466.     if(idx.offset<smb.status.header_offset) {
  467.         fprintf(stderr,"%sInvalid offset\n",beep);
  468.         idxofferr++;
  469.         break; }
  470.     if(idx.number==0) {
  471.         fprintf(stderr,"%sZero message number\n",beep);
  472.         idxzeronum++;
  473.         break; }
  474.     if(idx.number>smb.status.last_msg) {
  475.         fprintf(stderr,"%sOut-Of-Range message number\n",beep);
  476.         idxnumerr++;
  477.         break; }
  478.     number[l]=idx.number;
  479.     offset[l]=idx.offset; }
  480.  
  481. if(l<total) {
  482.     fprintf(stderr,"%sError reading index record\n",beep);
  483.     idxerr=1; }
  484. else {
  485.     fprintf(stderr,"\r%79s\r","");
  486.     for(m=0;m<total;m++) {
  487.         fprintf(stderr,"\r%2lu%%  %5lu ",m ? (long)(100.0/((float)total/m)) : 0,m);
  488.         fprintf(stderr,"#%-5lu (%06lX) 2nd Pass ",number[m],offset[m]);
  489.         for(n=0;n<m;n++)
  490.             if(number[m] && number[n] && number[m]<number[n]) {
  491.                 fprintf(stderr,"%sMisordered message number\n",beep);
  492.                 misnumbered++;
  493.                 number[n]=0;
  494.                 break; } }
  495.     fprintf(stderr,"\r%79s\r100%%\n",""); }
  496. FREE(number);
  497. FREE(offset);
  498.  
  499. }    /* if(total) */
  500.  
  501. totalmsgs+=smb.status.total_msgs;
  502. totalmsgbytes+=(acthdrblocks*SHD_BLOCK_LEN)+(actdatblocks*SDT_BLOCK_LEN);
  503. totaldelmsgs+=deleted;
  504. totallzhsaved+=lzhsaved;
  505. printf("\n");
  506. printf("%-35.35s (=): %lu\n"
  507.     ,"Status Total"
  508.     ,smb.status.total_msgs);
  509. printf("%-35.35s (=): %lu\n"
  510.     ,"Index Records"
  511.     ,total);
  512. printf("%-35.35s (=): %lu\n"
  513.     ,"Active Headers"
  514.     ,headers-deleted);
  515. printf("%-35.35s ( ): %-8lu %13s bytes used\n"
  516.     ,"Active Header Blocks"
  517.     ,acthdrblocks,ultoac(acthdrblocks*SHD_BLOCK_LEN,str));
  518. printf("%-35.35s ( ): %-8lu %13s bytes used\n"
  519.     ,"Active Data Blocks"
  520.     ,actdatblocks,ultoac(actdatblocks*SDT_BLOCK_LEN,str));
  521. if(lzhblocks)
  522.     printf("%-35.35s ( ): %-8lu %13s bytes saved\n"
  523.         ,"Active LZH Compressed Data Blocks"
  524.         ,lzhblocks,ultoac(lzhsaved,str));
  525. printf("%-35.35s ( ): %lu\n"
  526.     ,"Header Records"
  527.     ,headers);
  528. printf("%-35.35s ( ): %lu\n"
  529.     ,"Deleted Headers"
  530.     ,deleted);
  531. printf("%-35.35s ( ): %-8lu %13s bytes used\n"
  532.     ,"Deleted Header Blocks"
  533.     ,delhdrblocks,ultoac(delhdrblocks*SHD_BLOCK_LEN,str));
  534. packable+=(delhdrblocks*SHD_BLOCK_LEN);
  535. printf("%-35.35s ( ): %-8lu %13s bytes used\n"
  536.     ,"Deleted Data Blocks"
  537.     ,deldatblocks,ultoac(deldatblocks*SDT_BLOCK_LEN,str));
  538. packable+=(deldatblocks*SDT_BLOCK_LEN);
  539.  
  540. if(orphan)
  541.     printf("%-35.35s (!): %lu\n"
  542.         ,"Orphaned Headers"
  543.         ,orphan);
  544. if(idxzeronum)
  545.     printf("%-35.35s (!): %lu\n"
  546.         ,"Zeroed Index Numbers"
  547.         ,idxzeronum);
  548. if(zeronum)
  549.     printf("%-35.35s (!): %lu\n"
  550.         ,"Zeroed Header Numbers"
  551.         ,zeronum);
  552. /***
  553. if(delidx)
  554.     printf("%-35.35s (!): %lu\n"
  555.         ,"Deleted Index Records"
  556.         ,delidx);
  557. ***/
  558. if(idxofferr)
  559.     printf("%-35.35s (!): %lu\n"
  560.         ,"Invalid Index Offsets"
  561.         ,idxofferr);
  562. if(dupenum)
  563.     printf("%-35.35s (!): %lu\n"
  564.         ,"Duplicate Index Numbers"
  565.         ,dupenum);
  566. if(dupeoff)
  567.     printf("%-35.35s (!): %lu\n"
  568.         ,"Duplicate Index Offsets"
  569.         ,dupeoff);
  570. if(dupenumhdr)
  571.     printf("%-35.35s (!): %lu\n"
  572.         ,"Duplicate Header Numbers"
  573.         ,dupenumhdr);
  574. if(misnumbered)
  575.     printf("%-35.35s (!): %lu\n"
  576.         ,"Misordered Index Numbers"
  577.         ,misnumbered);
  578. if(lockerr)
  579.     printf("%-35.35s (!): %lu\n"
  580.         ,"Unlockable Header Records"
  581.         ,lockerr);
  582. if(hdrerr)
  583.     printf("%-35.35s (!): %lu\n"
  584.         ,"Unreadable Header Records"
  585.         ,hdrerr);
  586. if(idxnumerr)
  587.     printf("%-35.35s (!): %lu\n"
  588.         ,"Out-Of-Range Index Numbers"
  589.         ,idxnumerr);
  590. if(hdrnumerr)
  591.     printf("%-35.35s (!): %lu\n"
  592.         ,"Out-Of-Range Header Numbers"
  593.         ,hdrnumerr);
  594. if(attr)
  595.     printf("%-35.35s (!): %lu\n"
  596.         ,"Mismatched Header Attributes"
  597.         ,attr);
  598. if(timeerr)
  599.     printf("%-35.35s (!): %lu\n"
  600.         ,"Mismatched Header Import Time"
  601.         ,timeerr);
  602. if(xlaterr)
  603.     printf("%-35.35s (!): %lu\n"
  604.         ,"Unsupported Translation Types"
  605.         ,xlaterr);
  606. if(datactalloc)
  607.     printf("%-35.35s (!): %lu\n"
  608.         ,"Misallocated Active Data Blocks"
  609.         ,datactalloc);
  610. if(actalloc)
  611.     printf("%-35.35s (!): %lu\n"
  612.         ,"Misallocated Active Header Blocks"
  613.         ,actalloc);
  614. /***
  615. if(delalloc)
  616.     printf("%-35.35s (!): %lu\n"
  617.         ,"Misallocated Deleted Header Blocks"
  618.         ,delalloc);
  619. ***/
  620.  
  621. if(dfieldoffset)
  622.     printf("%-35.35s (!): %lu\n"
  623.         ,"Invalid Data Field Offsets"
  624.         ,dfieldoffset);
  625.  
  626. if(dfieldlength)
  627.     printf("%-35.35s (!): %lu\n"
  628.         ,"Invalid Data Field Lengths"
  629.         ,dfieldlength);
  630.  
  631.  
  632. printf("\n%s Message Base ",smb.file);
  633. if((headers-deleted)!=smb.status.total_msgs || total!=smb.status.total_msgs
  634.     || (headers-deleted)!=total || idxzeronum || zeronum
  635.     || orphan || dupenumhdr || dupenum || dupeoff || attr
  636.     || lockerr || hdrerr || hdrnumerr || idxnumerr || idxofferr
  637.     || actalloc || datactalloc || misnumbered || timeerr
  638.     || dfieldoffset || dfieldlength || xlaterr || idxerr) {
  639.     printf("%shas Errors!\n",beep);
  640.     errors++; }
  641. else
  642.     printf("is OK\n");
  643.  
  644. smb_unlocksmbhdr(&smb);
  645. smb_close(&smb);
  646. }
  647.  
  648. if((totalmsgs && (totalmsgs!=smb.status.total_msgs || totallzhmsgs))
  649.     || packable)
  650.     printf("\n");
  651. if(totalmsgs && totalmsgs!=smb.status.total_msgs)
  652.     printf("%-39.39s: %-8lu %13s bytes used\n"
  653.         ,"Total Active Messages"
  654.         ,totalmsgs,ultoac(totalmsgbytes,str));
  655. if(totallzhmsgs && totalmsgs!=smb.status.total_msgs)
  656.     printf("%-39.39s: %-8lu %13s bytes saved\n"
  657.         ,"Total LZH Compressed Messages"
  658.         ,totallzhmsgs,ultoac(totallzhsaved,str));
  659. if(packable)
  660.     printf("%-39.39s: %-8lu %13s bytes used\n"
  661.         ,"Total Deleted Messages"
  662.         ,totaldelmsgs,ultoac(packable,str));
  663.  
  664. if(pause_on_error && errlast!=errors) {
  665.     fprintf(stderr,"\7\nHit any key to continue...");
  666.     if(!getch())
  667.         getch();
  668.     fprintf(stderr,"\n"); }
  669.  
  670.  
  671. return(errors);
  672. }
  673.