home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / BBS / SMB_111.ZIP / SMBUTIL.C < prev    next >
C/C++ Source or Header  |  1994-06-02  |  34KB  |  1,317 lines

  1. /* SMBUTIL.C */
  2.  
  3. /* Synchronet Message Base Utility */
  4.  
  5. #define SMBUTIL_VER "1.11"
  6.  
  7. #include "smblib.h"
  8. #include "smbutil.h"
  9. #include "crc32.h"
  10.  
  11. extern long timezone=0;   /* Fix for Borland C++ EST default */
  12. extern int daylight=0;      /* Fix for Borland C++ EDT default */
  13.  
  14. /********************/
  15. /* Global variables */
  16. /********************/
  17.  
  18. ulong mode=0L;
  19. ushort tzone=PST;
  20. char filein[128];
  21. char attach[128];
  22.  
  23. /************************/
  24. /* Program usage/syntax */
  25. /************************/
  26.  
  27. char *usage=
  28. "usage: smbutil [/opts] cmd <filespec.SHD>\n"
  29. "\n"
  30. "cmd:\n"
  31. "       l[n] = list msgs starting at number n\n"
  32. "       r[n] = read msgs starting at number n\n"
  33. "       v[n] = view msg headers starting at number n\n"
  34. "       k[n] = kill (delete) n msgs\n"
  35. "       i<f> = import from text file f\n"
  36. "       s    = display msg base status\n"
  37. "       c    = change msg base status\n"
  38. "       m    = maintain msg base - delete old msgs and msgs over max\n"
  39. "       p[k] = pack msg base (k specifies minimum packable Kbytes)\n"
  40. "opts:\n"
  41. "       a    = always pack msg base (disable compression analysis)\n"
  42. "       f    = fast msg creation mode\n"
  43. "       d    = disable duplicate message checking\n"
  44. "       z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
  45. ;
  46.  
  47. /****************************************************************************/
  48. /* Checks the disk drive for the existence of a file. Returns 1 if it       */
  49. /* exists, 0 if it doesn't.                                                 */
  50. /****************************************************************************/
  51. char fexist(char *filespec)
  52. {
  53.     struct ffblk f;
  54.  
  55. if(findfirst(filespec,&f,0)==0)
  56.     return(1);
  57. return(0);
  58. }
  59.  
  60. /****************************************************************************/
  61. /* Returns the length of the file in 'filespec'                             */
  62. /****************************************************************************/
  63. long flength(char *filespec)
  64. {
  65.     struct ffblk f;
  66.  
  67. if(findfirst(filespec,&f,0)==0)
  68.     return(f.ff_fsize);
  69. return(-1L);
  70. }
  71.  
  72. /****************************************************************************/
  73. /* Updates 16-bit "rcrc" with character 'ch'                                */
  74. /****************************************************************************/
  75. void ucrc16(uchar ch, ushort *rcrc) {
  76.     ushort i, cy;
  77.     uchar nch=ch;
  78.  
  79. for (i=0; i<8; i++) {
  80.     cy=*rcrc & 0x8000;
  81.     *rcrc<<=1;
  82.     if (nch & 0x80) *rcrc |= 1;
  83.     nch<<=1;
  84.     if (cy) *rcrc ^= 0x1021; }
  85. }
  86.  
  87. /****************************************************************************/
  88. /* Returns 16-crc of string (not counting terminating NULL)                 */
  89. /****************************************************************************/
  90. ushort crc16(char *str)
  91. {
  92.     int     i=0;
  93.     ushort    crc=0;
  94.  
  95. ucrc16(0,&crc);
  96. while(str[i])
  97.     ucrc16(str[i++],&crc);
  98. ucrc16(0,&crc);
  99. ucrc16(0,&crc);
  100. return(crc);
  101. }
  102.  
  103. /****************************************************************************/
  104. /* Adds a new message to the message base                                    */
  105. /****************************************************************************/
  106. void postmsg(smbstatus_t status)
  107. {
  108.     char    str[128],buf[SDT_BLOCK_LEN];
  109.     ushort    xlat;
  110.     int     i,j,k,file;
  111.     long    length;
  112.     ulong    offset,crc=0xffffffffUL;
  113.     FILE    *instream;
  114.     smbmsg_t    msg;
  115.  
  116. if(!filelength(fileno(shd_fp)))
  117.     smb_create(2000,2000,0,10);
  118. length=flength(filein);
  119. if(length<1L) {
  120.     printf("Invalid file size for '%s'\n",filein);
  121.     exit(1); }
  122. length+=2;    /* for translation string */
  123. i=smb_open_da(10);
  124. if(i) {
  125.     printf("smb_open_da returned %d\n",i);
  126.     exit(1); }
  127. if(mode&FAST)
  128.     offset=smb_fallocdat(length,1);
  129. else
  130.     offset=smb_allocdat(length,1);
  131. fclose(sda_fp);
  132. if((file=open(filein,O_RDONLY|O_BINARY))==-1
  133.     || (instream=fdopen(file,"rb"))==NULL) {
  134.     printf("Error opening %s for read\n",filein);
  135.     smb_freemsgdat(offset,length,1);
  136.     exit(1); }
  137. setvbuf(instream,NULL,_IOFBF,32*1024);
  138. fseek(sdt_fp,offset,SEEK_SET);
  139. xlat=XLAT_NONE;
  140. fwrite(&xlat,2,1,sdt_fp);
  141. k=SDT_BLOCK_LEN-2;
  142. while(!feof(instream)) {
  143.     memset(buf,NULL,k);
  144.     j=fread(buf,1,k,instream);
  145.     if(!(mode&NOCRC)) {
  146.         for(i=0;i<j;i++)
  147.             crc=ucrc32(buf[i],crc); }
  148.     fwrite(buf,k,1,sdt_fp);
  149.     k=SDT_BLOCK_LEN; }
  150. fclose(instream);
  151. crc=~crc;
  152.  
  153. memset(&msg,0,sizeof(smbmsg_t));
  154. memcpy(msg.hdr.id,"SHD\x1a",4);
  155. msg.hdr.version=SMB_VERSION;
  156. msg.hdr.when_written.time=time(NULL);
  157. msg.hdr.when_written.zone=tzone;
  158.  
  159. if(!(mode&NOCRC)) {
  160.     i=smb_addcrc(status.max_crcs,crc,10);
  161.     if(i) {
  162.         printf("smb_addcrc returned %d\n",i);
  163.         smb_freemsgdat(offset,length,1);
  164.         exit(1); } }
  165.  
  166. msg.hdr.offset=offset;
  167.  
  168. printf("To: ");
  169. gets(str);
  170. i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
  171. if(i) {
  172.     printf("smb_hfield returned %d\n",i);
  173.     smb_freemsgdat(offset,length,1);
  174.     exit(1); }
  175. strlwr(str);
  176. msg.idx.to=crc16(str);
  177.  
  178. printf("From: ");
  179. gets(str);
  180. i=smb_hfield(&msg,SENDER,strlen(str),str);
  181. if(i) {
  182.     printf("smb_hfield returned %d\n",i);
  183.     smb_freemsgdat(offset,length,1);
  184.     exit(1); }
  185. strlwr(str);
  186. msg.idx.from=crc16(str);
  187.  
  188. printf("Subj: ");
  189. gets(str);
  190. i=smb_hfield(&msg,SUBJECT,strlen(str),str);
  191. if(i) {
  192.     printf("smb_hfield returned %d\n",i);
  193.     smb_freemsgdat(offset,length,1);
  194.     exit(1); }
  195. strlwr(str);
  196. msg.idx.subj=crc16(str);
  197.  
  198. i=smb_dfield(&msg,TEXT_BODY,length);
  199. if(i) {
  200.     printf("smb_dfield returned %d\n",i);
  201.     smb_freemsgdat(offset,length,1);
  202.     exit(1); }
  203.  
  204. i=smb_addmsghdr(&msg,&status,mode&FAST,10);
  205.  
  206. if(i) {
  207.     printf("smb_addmsghdr returned %d\n",i);
  208.     smb_freemsgdat(offset,length,1);
  209.     exit(1); }
  210. smb_freemsgmem(msg);
  211.  
  212. }
  213.  
  214. /****************************************************************************/
  215. /* Shows the message base header                                            */
  216. /****************************************************************************/
  217. void showstatus()
  218. {
  219.     int i;
  220.     smbstatus_t status;
  221.  
  222. i=smb_locksmbhdr(10);
  223. if(i) {
  224.     printf("smb_locksmbhdr returned %d\n",i);
  225.     return; }
  226. i=smb_getstatus(&status);
  227. smb_unlocksmbhdr();
  228. if(i) {
  229.     printf("smb_getstatus returned %d\n",i);
  230.     return; }
  231. printf("last_msg        =%lu\n"
  232.        "total_msgs      =%lu\n"
  233.        "header_offset   =%lu\n"
  234.        "max_crcs        =%lu\n"
  235.        "max_msgs        =%lu\n"
  236.        "max_age         =%u\n"
  237.        "reserved        =%04Xh\n"
  238.        ,status.last_msg
  239.        ,status.total_msgs
  240.        ,status.header_offset
  241.        ,status.max_crcs
  242.        ,status.max_msgs
  243.        ,status.max_age
  244.        ,status.reserved
  245.        );
  246. }
  247.  
  248. /****************************************************************************/
  249. /* Configure message base header                                            */
  250. /****************************************************************************/
  251. void config()
  252. {
  253.     char max_msgs[128],max_crcs[128],max_age[128];
  254.     int i;
  255.     smbstatus_t status;
  256.  
  257. i=smb_locksmbhdr(10);
  258. if(i) {
  259.     printf("smb_locksmbhdr returned %d\n",i);
  260.     return; }
  261. i=smb_getstatus(&status);
  262. smb_unlocksmbhdr();
  263. if(i) {
  264.     printf("smb_getstatus returned %d\n",i);
  265.     return; }
  266. printf("Max msgs =%-5lu  New value (CR=No Change): ",status.max_msgs);
  267. gets(max_msgs);
  268. printf("Max crcs =%-5lu  New value (CR=No Change): ",status.max_crcs);
  269. gets(max_crcs);
  270. printf("Max age  =%-5u  New value (CR=No Change): ",status.max_age);
  271. gets(max_age);
  272. i=smb_locksmbhdr(10);
  273. if(i) {
  274.     printf("smb_locksmbhdr returned %d\n",i);
  275.     return; }
  276. i=smb_getstatus(&status);
  277. if(i) {
  278.     printf("smb_getstatus returned %d\n",i);
  279.     smb_unlocksmbhdr();
  280.     return; }
  281. if(isdigit(max_msgs[0]))
  282.     status.max_msgs=atol(max_msgs);
  283. if(isdigit(max_crcs[0]))
  284.     status.max_crcs=atol(max_crcs);
  285. if(isdigit(max_age[0]))
  286.     status.max_age=atoi(max_age);
  287. i=smb_putstatus(status);
  288. smb_unlocksmbhdr();
  289. if(i)
  290.     printf("smb_putstatus returned %d\n",i);
  291. }
  292.  
  293. /****************************************************************************/
  294. /* Lists messages' to, from, and subject                                    */
  295. /****************************************************************************/
  296. void listmsgs(ulong start, ulong count)
  297. {
  298.     int i;
  299.     ulong l=0;
  300.     smbmsg_t msg;
  301.     idxrec_t idxrec;
  302.  
  303. if(!start)
  304.     start=1;
  305. fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
  306. while(l<count) {
  307.     if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  308.         break;
  309.     i=smb_lockmsghdr(msg,10);
  310.     if(i) {
  311.         printf("smb_lockmsghdr returned %d\n",i);
  312.         break; }
  313.     i=smb_getmsghdr(&msg);
  314.     smb_unlockmsghdr(msg);
  315.     if(i) {
  316.         printf("smb_getmsghdr returned %d\n",i);
  317.         break; }
  318.     printf("%4lu %-25.25s %-25.25s %.20s\n"
  319.         ,msg.hdr.number,msg.from,msg.to,msg.subj);
  320.     smb_freemsgmem(msg);
  321.     l++; }
  322. }
  323.  
  324. /****************************************************************************/
  325. /* Returns an ASCII string for FidoNet address 'addr'                       */
  326. /****************************************************************************/
  327. char *faddrtoa(fidoaddr_t addr)
  328. {
  329.     static char str[25];
  330.     char point[25];
  331.  
  332. sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
  333. if(addr.point) {
  334.     sprintf(point,".%u",addr.point);
  335.     strcat(str,point); }
  336. return(str);
  337. }
  338.  
  339. char *binstr(uchar *buf, ushort length)
  340. {
  341.     static char str[128];
  342.     char tmp[128];
  343.     int i;
  344.  
  345. str[0]=0;
  346. for(i=0;i<length;i++)
  347.     if(buf[i] && (buf[i]<SP || buf[i]>=0x7f))
  348.         break;
  349. if(i==length)        /* not binary */
  350.     return(buf);
  351. for(i=0;i<length;i++) {
  352.     sprintf(tmp,"%02X ",buf[i]);
  353.     strcat(str,tmp); }
  354. return(str);
  355. }
  356.  
  357. /****************************************************************************/
  358. /* Converts when_t.zone into ASCII format                                    */
  359. /****************************************************************************/
  360. char *zonestr(short zone)
  361. {
  362.     static char str[32];
  363.  
  364. switch(zone) {
  365.     case 0:     return("UT");
  366.     case AST:    return("AST");
  367.     case EST:    return("EST");
  368.     case CST:    return("CST");
  369.     case MST:    return("MST");
  370.     case PST:    return("PST");
  371.     case YST:    return("YST");
  372.     case HST:    return("HST");
  373.     case BST:    return("BST");
  374.     case ADT:    return("ADT");
  375.     case EDT:    return("EDT");
  376.     case CDT:    return("CDT");
  377.     case MDT:    return("MDT");
  378.     case PDT:    return("PDT");
  379.     case YDT:    return("YDT");
  380.     case HDT:    return("HDT");
  381.     case BDT:    return("BDT");
  382.     case MID:    return("MID");
  383.     case VAN:    return("VAN");
  384.     case EDM:    return("EDM");
  385.     case WIN:    return("WIN");
  386.     case BOG:    return("BOG");
  387.     case CAR:    return("CAR");
  388.     case RIO:    return("RIO");
  389.     case FER:    return("FER");
  390.     case AZO:    return("AZO");
  391.     case LON:    return("LON");
  392.     case BER:    return("BER");
  393.     case ATH:    return("ATH");
  394.     case MOS:    return("MOS");
  395.     case DUB:    return("DUB");
  396.     case KAB:    return("KAB");
  397.     case KAR:    return("KAR");
  398.     case BOM:    return("BOM");
  399.     case KAT:    return("KAT");
  400.     case DHA:    return("DHA");
  401.     case BAN:    return("BAN");
  402.     case HON:    return("HON");
  403.     case TOK:    return("TOK");
  404.     case SYD:    return("SYD");
  405.     case NOU:    return("NOU");
  406.     case WEL:    return("WEL");
  407.     }
  408.  
  409. sprintf(str,"%02d:%02d",zone/60,zone<0 ? (-zone)%60 : zone%60);
  410. return(str);
  411. }
  412.              
  413.  
  414. /****************************************************************************/
  415. /* Displays message header information                                        */
  416. /****************************************************************************/
  417. void viewmsgs(ulong start, ulong count)
  418. {
  419.     char when_written[128]
  420.         ,when_imported[128];
  421.     int i;
  422.     ulong l=0;
  423.     smbmsg_t msg;
  424.     idxrec_t idxrec;
  425.  
  426. if(!start)
  427.     start=1;
  428. fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
  429. while(l<count) {
  430.     if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  431.         break;
  432.     i=smb_lockmsghdr(msg,10);
  433.     if(i) {
  434.         printf("smb_lockmsghdr returned %d\n",i);
  435.         break; }
  436.     i=smb_getmsghdr(&msg);
  437.     smb_unlockmsghdr(msg);
  438.     if(i) {
  439.         printf("smb_getmsghdr returned %d\n",i);
  440.         break; }
  441.  
  442.     sprintf(when_written,"%.24s %s"
  443.         ,ctime((time_t *)&msg.hdr.when_written.time)
  444.         ,zonestr(msg.hdr.when_written.zone));
  445.     sprintf(when_imported,"%.24s %s"
  446.         ,ctime((time_t *)&msg.hdr.when_imported.time)
  447.         ,zonestr(msg.hdr.when_imported.zone));
  448.  
  449.     printf( "%-20.20s %s\n"
  450.             "%-20.20s %s\n"
  451.             "%-20.20s %s\n"
  452.             "%-20.20s %04Xh\n"
  453.             "%-20.20s %04Xh\n"
  454.             "%-20.20s %u\n"
  455.             "%-20.20s %04Xh\n"
  456.             "%-20.20s %08lXh\n"
  457.             "%-20.20s %08lXh\n"
  458.             "%-20.20s %s\n"
  459.             "%-20.20s %s\n"
  460.             "%-20.20s %ld\n"
  461.             "%-20.20s %ld\n"
  462.             "%-20.20s %ld\n"
  463.             "%-20.20s %ld\n"
  464.             "%-20.20s %s\n"
  465.             "%-20.20s %ld\n"
  466.             "%-20.20s %u\n",
  467.  
  468.         "subj",
  469.         msg.subj,
  470.  
  471.         "from",
  472.         msg.from,
  473.  
  474.         "to",
  475.         msg.to,
  476.  
  477.         "type",
  478.         msg.hdr.type,
  479.  
  480.         "version",
  481.         msg.hdr.version,
  482.  
  483.         "length",
  484.         msg.hdr.length,
  485.  
  486.         "attr",
  487.         msg.hdr.attr,
  488.  
  489.         "auxattr",
  490.         msg.hdr.auxattr,
  491.  
  492.         "netattr",
  493.         msg.hdr.netattr,
  494.  
  495.         "when_written",
  496.         when_written,
  497.  
  498.         "when_imported",
  499.         when_imported,
  500.  
  501.         "number",
  502.         msg.hdr.number,
  503.  
  504.         "thread_orig",
  505.         msg.hdr.thread_orig,
  506.  
  507.         "thread_next",
  508.         msg.hdr.thread_next,
  509.  
  510.         "thread_first",
  511.         msg.hdr.thread_first,
  512.  
  513.         "reserved[16]",
  514.         binstr(msg.hdr.reserved,16),
  515.  
  516.         "offset",
  517.         msg.hdr.offset,
  518.  
  519.         "total_dfields",
  520.         msg.hdr.total_dfields
  521.         );
  522.     for(i=0;i<msg.hdr.total_dfields;i++)
  523.         printf("dfield[%u].type       %02Xh\n"
  524.                "dfield[%u].offset     %lu\n"
  525.                "dfield[%u].length     %d\n"
  526.                ,i,msg.dfield[i].type
  527.                ,i,msg.dfield[i].offset
  528.                ,i,msg.dfield[i].length);
  529.  
  530.     for(i=0;i<msg.total_hfields;i++)
  531.         printf("hfield[%u].type       %02Xh\n"
  532.                "hfield[%u].length     %d\n"
  533.                "hfield[%u]_dat        %s\n"
  534.                ,i,msg.hfield[i].type
  535.                ,i,msg.hfield[i].length
  536.                ,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
  537.  
  538.     if(msg.from_net.type)
  539.         printf("from_net.type        %02Xh\n"
  540.                "from_net.addr        %s\n"
  541.             ,msg.from_net.type
  542.             ,msg.from_net.type==NET_FIDO
  543.             ? faddrtoa(*(fidoaddr_t *)msg.from_net.addr) : msg.from_net.addr);
  544.  
  545.     if(msg.to_net.type)
  546.         printf("to_net.type          %02Xh\n"
  547.                 "to_net.addr         %s\n"
  548.             ,msg.to_net.type
  549.             ,msg.to_net.type==NET_FIDO
  550.             ? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
  551.  
  552.     if(msg.replyto_net.type)
  553.         printf("replyto_net.type     %02Xh\n"
  554.                "replyto_net.addr     %s\n"
  555.             ,msg.replyto_net.type
  556.             ,msg.replyto_net.type==NET_FIDO
  557.             ? faddrtoa(*(fidoaddr_t *)msg.replyto_net.addr)
  558.                 : msg.replyto_net.addr);
  559.  
  560.     printf("from_agent           %02Xh\n"
  561.            "to_agent             %02Xh\n"
  562.            "replyto_agent        %02Xh\n"
  563.            ,msg.from_agent
  564.            ,msg.to_agent
  565.            ,msg.replyto_agent);
  566.  
  567.     printf("\n");
  568.     smb_freemsgmem(msg);
  569.     l++; }
  570. }
  571.  
  572. /****************************************************************************/
  573. /* Maintain message base - deletes messages older than max age (in days)    */
  574. /* or messages that exceed maximum                                            */
  575. /****************************************************************************/
  576. void maint(void)
  577. {
  578.     int i;
  579.     ulong l,m,n,f,flagged=0;
  580.     time_t now;
  581.     smbstatus_t status;
  582.     smbmsg_t msg;
  583.     idxrec_t huge *idx;
  584.  
  585. printf("Maintaining message base...\r\n");
  586. now=time(NULL);
  587. i=smb_locksmbhdr(10);
  588. if(i) {
  589.     printf("smb_locksmbhdr returned %d\n",i);
  590.     return; }
  591. i=smb_getstatus(&status);
  592. if(i) {
  593.     smb_unlocksmbhdr();
  594.     printf("smb_getstatus returned %d\n",i);
  595.     return; }
  596. if(!status.total_msgs) {
  597.     smb_unlocksmbhdr();
  598.     printf("Empty\n");
  599.     return; }
  600. printf("Loading index...\n");
  601. if((idx=(idxrec_t *)MALLOC(sizeof(idxrec_t)*status.total_msgs))
  602.     ==NULL) {
  603.     smb_unlocksmbhdr();
  604.     printf("can't allocate %lu bytes of memory\n"
  605.         ,sizeof(idxrec_t)*status.total_msgs);
  606.     return; }
  607. fseek(sid_fp,0L,SEEK_SET);
  608. for(l=0;l<status.total_msgs;l++) {
  609.     printf("%lu of %lu\r"
  610.         ,l+1,status.total_msgs);
  611.     if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
  612.         break; }
  613. printf("\nDone.\n\n");
  614.  
  615. if(status.max_age) {
  616.     printf("Scanning for messages more than %u days old...\n"
  617.         ,status.max_age);
  618.     for(m=0;m<l;m++) {
  619.         printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
  620.         if(idx[m].attr&MSG_PERMANENT)
  621.             continue;
  622.         if((now-idx[m].time)/(24L*60L*60L)>status.max_age) {
  623.             flagged++;
  624.             idx[m].attr|=MSG_DELETE; } }  /* mark for deletion */
  625.     printf("\r100%% (%lu flagged for deletion)\n",flagged); }
  626.  
  627. printf("Scanning for read messages to be killed...\n");
  628. for(m=f=0;m<l;m++) {
  629.     printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
  630.     if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
  631.         continue;
  632.     if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
  633.         f++;
  634.         flagged++;
  635.         idx[m].attr|=MSG_DELETE; } }
  636. printf("\r100%% (%lu flagged for deletion)\n",f);
  637.  
  638. if(l-flagged>status.max_msgs) {
  639.     printf("Flagging excess messages for deletion...\n");
  640.     for(m=n=0,f=flagged;l-flagged>status.max_msgs && m<l;m++) {
  641.         if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
  642.             continue;
  643.         printf("%lu of %lu\r",++n,(l-f)-status.max_msgs);
  644.         flagged++;
  645.         idx[m].attr|=MSG_DELETE; }            /* mark for deletion */
  646.     printf("\nDone.\n\n"); }
  647.  
  648. if(!flagged) {                /* No messages to delete */
  649.     FREE(idx);
  650.     smb_unlocksmbhdr();
  651.     return; }
  652.  
  653. printf("Freeing allocated header and data blocks for deleted messages...\n");
  654. i=smb_open_da(10);
  655. if(i) {
  656.     smb_unlocksmbhdr();
  657.     printf("smb_open_da returned %d\n",i);
  658.     exit(1); }
  659. i=smb_open_ha(10);
  660. if(i) {
  661.     smb_unlocksmbhdr();
  662.     printf("smb_open_ha returned %d\n",i);
  663.     exit(1); }
  664. for(m=n=0;m<l;m++) {
  665.     if(idx[m].attr&MSG_DELETE) {
  666.         printf("%lu of %lu\r",++n,flagged);
  667.         msg.idx=idx[m];
  668.         msg.hdr.number=msg.idx.number;
  669.         if((i=smb_getmsgidx(&msg))!=0) {
  670.             smb_unlockmsghdr(msg);
  671.             printf("\nsmb_getmsgidx returned %d\n",i);
  672.             break; }
  673.         i=smb_lockmsghdr(msg,10);
  674.         if(i) {
  675.             printf("\nsmb_lockmsghdr returned %d\n",i);
  676.             break; }
  677.         if((i=smb_getmsghdr(&msg))!=0) {
  678.             smb_unlockmsghdr(msg);
  679.             printf("\nsmb_getmsghdr returned %d\n",i);
  680.             break; }
  681.         msg.hdr.attr|=MSG_DELETE;            /* mark header as deleted */
  682.         if((i=smb_putmsg(msg))!=0) {
  683.             smb_freemsgmem(msg);
  684.             smb_unlockmsghdr(msg);
  685.             printf("\nsmb_putmsg returned %d\n",i);
  686.             break; }
  687.         smb_unlockmsghdr(msg);
  688.         if((i=smb_freemsg(msg,status))!=0) {
  689.             smb_freemsgmem(msg);
  690.             printf("\nsmb_freemsg returned %d\n",i);
  691.             break; }
  692.         smb_freemsgmem(msg); } }
  693. fclose(sha_fp);
  694. fclose(sda_fp);
  695. printf("\nDone.\n\n");
  696.  
  697. printf("Re-writing index...\n");
  698. rewind(sid_fp);
  699. if(chsize(fileno(sid_fp),0L))
  700.     printf("chsize failed!\n");
  701. for(m=n=0;m<l;m++) {
  702.     if(idx[m].attr&MSG_DELETE)
  703.         continue;
  704.     printf("%lu of %lu\r",++n,l-flagged);
  705.     fwrite(&idx[m],sizeof(idxrec_t),1,sid_fp); }
  706. printf("\nDone.\n\n");
  707. fflush(sid_fp);
  708.  
  709. FREE(idx);
  710. status.total_msgs-=flagged;
  711. smb_putstatus(status);
  712. smb_unlocksmbhdr();
  713. }
  714.  
  715. /****************************************************************************/
  716. /* Kills 'msgs' number of messags                                           */
  717. /* Returns actual number of messages killed.                                */
  718. /****************************************************************************/
  719. ulong kill(ulong msgs)
  720. {
  721.     int i;
  722.     ulong l,m,n,flagged=0;
  723.     smbstatus_t status;
  724.     smbmsg_t msg;
  725.     idxrec_t *idx;
  726.  
  727. i=smb_locksmbhdr(10);
  728. if(i) {
  729.     printf("smb_locksmbhdr returned %d\n",i);
  730.     return(0); }
  731. i=smb_getstatus(&status);
  732. if(i) {
  733.     smb_unlocksmbhdr();
  734.     printf("smb_getstatus returned %d\n",i);
  735.     return(0); }
  736. printf("Loading index...\n");
  737. if((idx=(idxrec_t *)MALLOC(sizeof(idxrec_t)*status.total_msgs))
  738.     ==NULL) {
  739.     smb_unlocksmbhdr();
  740.     printf("can't allocate %lu bytes of memory\n"
  741.         ,sizeof(idxrec_t)*status.total_msgs);
  742.     return(0); }
  743. fseek(sid_fp,0L,SEEK_SET);
  744. for(l=0;l<status.total_msgs;l++) {
  745.     printf("%lu of %lu\r"
  746.         ,l+1,status.total_msgs);
  747.     if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
  748.         break; }
  749. printf("\nDone.\n\n");
  750.  
  751. printf("Flagging messages for deletion...\n");
  752. for(m=0;m<l && flagged<msgs;m++) {
  753.     if(idx[m].attr&(MSG_PERMANENT))
  754.         continue;
  755.     printf("%lu of %lu\r",++flagged,msgs);
  756.     idx[m].attr|=MSG_DELETE; }            /* mark for deletion */
  757. printf("\nDone.\n\n");
  758.  
  759. printf("Freeing allocated header and data blocks for deleted messages...\n");
  760. i=smb_open_da(10);
  761. if(i) {
  762.     smb_unlocksmbhdr();
  763.     printf("smb_open_da returned %d\n",i);
  764.     exit(1); }
  765. i=smb_open_ha(10);
  766. if(i) {
  767.     smb_unlocksmbhdr();
  768.     printf("smb_open_ha returned %d\n",i);
  769.     exit(1); }
  770. for(m=n=0;m<l;m++) {
  771.     if(idx[m].attr&MSG_DELETE) {
  772.         printf("%lu of %lu\r",++n,flagged);
  773.         msg.idx=idx[m];
  774.         i=smb_lockmsghdr(msg,10);
  775.         if(i) {
  776.             printf("\nsmb_lockmsghdr returned %d\n",i);
  777.             break; }
  778.         msg.hdr.number=msg.idx.number;
  779.         if((i=smb_getmsgidx(&msg))!=0) {
  780.             smb_unlockmsghdr(msg);
  781.             printf("\nsmb_getmsgidx returned %d\n",i);
  782.             break; }
  783.         if((i=smb_getmsghdr(&msg))!=0) {
  784.             smb_unlockmsghdr(msg);
  785.             printf("\nsmb_getmsghdr returned %d\n",i);
  786.             break; }
  787.         msg.hdr.attr|=MSG_DELETE;            /* mark header as deleted */
  788.         if((i=smb_putmsg(msg))!=0) {
  789.             smb_unlockmsghdr(msg);
  790.             printf("\nsmb_putmsg returned %d\n",i);
  791.             break; }
  792.         smb_unlockmsghdr(msg);
  793.         smb_freemsg(msg,status);
  794.         smb_freemsgmem(msg); } }
  795.  
  796. fclose(sha_fp);
  797. fclose(sda_fp);
  798. printf("\nDone.\n\n");
  799.  
  800. printf("Re-writing index...\n");
  801. rewind(sid_fp);
  802. chsize(fileno(sid_fp),0L);
  803. for(m=n=0;m<l;m++) {
  804.     if(idx[m].attr&MSG_DELETE)
  805.         continue;
  806.     printf("%lu of %lu\r",++n,l-flagged);
  807.     fwrite(&idx[m],1,sizeof(idxrec_t),sid_fp); }
  808. printf("\nDone.\n\n");
  809.  
  810. fflush(sid_fp);
  811.  
  812. FREE(idx);
  813. status.total_msgs-=flagged;
  814. smb_putstatus(status);
  815. smb_unlocksmbhdr();
  816. return(flagged);
  817. }
  818.  
  819. typedef struct {
  820.     ulong old,new;
  821.     } datoffset_t;
  822.  
  823. /****************************************************************************/
  824. /* Removes all unused blocks from SDT and SHD files                         */
  825. /****************************************************************************/
  826. void packmsgs(ulong packable)
  827. {
  828.     uchar buf[SDT_BLOCK_LEN],ch;
  829.     int i,file;
  830.     ulong l,m,n,datoffsets=0,length,total=0;
  831.     FILE *tmp_sdt,*tmp_shd,*tmp_sid;
  832.     smbhdr_t    hdr;
  833.     smbstatus_t status;
  834.     smbmsg_t    msg;
  835.     datoffset_t *datoffset;
  836.  
  837. printf("Packing message base...\n");
  838. i=smb_locksmbhdr(10);
  839. if(i) {
  840.     printf("smb_locksmbhdr returned %d\n",i);
  841.     return; }
  842. i=smb_getstatus(&status);
  843. if(i) {
  844.     smb_unlocksmbhdr();
  845.     printf("smb_getstatus returned %d\n",i);
  846.     return; }
  847.  
  848. i=smb_open_ha(10);
  849. if(i) {
  850.     smb_unlocksmbhdr();
  851.     printf("smb_open_ha returned %d\n",i);
  852.     return; }
  853. i=smb_open_da(10);
  854. if(i) {
  855.     smb_unlocksmbhdr();
  856.     fclose(sha_fp);
  857.     printf("smb_open_da returned %d\n",i);
  858.     return; }
  859.  
  860. if(!status.total_msgs) {
  861.     printf("Empty\n");
  862.     rewind(shd_fp);
  863.     chsize(fileno(shd_fp),status.header_offset);
  864.     rewind(sdt_fp);
  865.     chsize(fileno(sdt_fp),0L);
  866.     rewind(sid_fp);
  867.     chsize(fileno(sid_fp),0L);
  868.     rewind(sha_fp);
  869.     chsize(fileno(sha_fp),0L);
  870.     rewind(sda_fp);
  871.     chsize(fileno(sda_fp),0L);
  872.     fclose(sha_fp);
  873.     fclose(sda_fp);
  874.     smb_unlocksmbhdr();
  875.     return; }
  876.  
  877.  
  878. if(!(mode&NOANALYSIS)) {
  879.     printf("Analyzing data blocks...\n");
  880.  
  881.     length=filelength(fileno(sda_fp));
  882.  
  883.     fseek(sda_fp,0L,SEEK_SET);
  884.     for(l=m=0;l<length;l+=2) {
  885.         printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
  886.         i=0;
  887.         if(!fread(&i,2,1,sda_fp))
  888.             break;
  889.         if(!i)
  890.             m++; }
  891.  
  892.     printf("\rAnalyzing header blocks...\n");
  893.  
  894.     length=filelength(fileno(sha_fp));
  895.  
  896.     fseek(sha_fp,0L,SEEK_SET);
  897.     for(l=n=0;l<length;l++) {
  898.         printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
  899.         ch=0;
  900.         if(!fread(&ch,1,1,sha_fp))
  901.             break;
  902.         if(!ch)
  903.             n++; }
  904.  
  905.     if(!m && !n) {
  906.         printf("\rAlready compressed.\n\n");
  907.         fclose(sha_fp);
  908.         fclose(sda_fp);
  909.         smb_unlocksmbhdr();
  910.         return; }
  911.  
  912.     if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
  913.         printf("\rLess than %luk compressable bytes.\n\n",packable);
  914.         fclose(sha_fp);
  915.         fclose(sda_fp);
  916.         smb_unlocksmbhdr();
  917.         return; }
  918.  
  919.     printf("\rCompressing %lu data blocks (%lu bytes)\n"
  920.              "        and %lu header blocks (%lu bytes)\n"
  921.               ,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN); }
  922.  
  923. rewind(sha_fp);
  924. chsize(fileno(sha_fp),0L);        /* Reset both allocation tables */
  925. rewind(sda_fp);
  926. chsize(fileno(sda_fp),0L);
  927.  
  928. tmp_sdt=tmpfile();
  929. tmp_shd=tmpfile();
  930. tmp_sid=tmpfile();
  931. if(!tmp_sdt || !tmp_shd || !tmp_sid) {
  932.     smb_unlocksmbhdr();
  933.     fclose(sha_fp);
  934.     fclose(sda_fp);
  935.     printf("error opening temp file\n");
  936.     return; }
  937. setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
  938. setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
  939. setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
  940. if((datoffset=(datoffset_t *)MALLOC(sizeof(datoffset_t)*status.total_msgs))
  941.     ==NULL) {
  942.     smb_unlocksmbhdr();
  943.     fclose(sha_fp);
  944.     fclose(sda_fp);
  945.     fclose(tmp_sdt);
  946.     fclose(tmp_shd);
  947.     fclose(tmp_sid);
  948.     printf("error allocating mem\n");
  949.     return; }
  950. fseek(shd_fp,0L,SEEK_SET);
  951. fread(&hdr,1,sizeof(smbhdr_t),shd_fp);
  952. fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
  953. fwrite(&status,1,sizeof(smbstatus_t),tmp_shd);
  954. for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<status.header_offset;l++) {
  955.     fread(&ch,1,1,shd_fp);            /* copy additional base header records */
  956.     fwrite(&ch,1,1,tmp_shd); }
  957. fseek(sid_fp,0L,SEEK_SET);
  958. for(l=0;l<status.total_msgs;l++) {
  959.     printf("%lu of %lu\r",l+1,status.total_msgs);
  960.     if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  961.         break;
  962.     if(msg.idx.attr&MSG_DELETE) {
  963.         printf("\nDeleted.\n");
  964.         continue; }
  965.     i=smb_lockmsghdr(msg,10);
  966.     if(i) {
  967.         printf("smb_lockmsghdr returned %d\n",i);
  968.         continue; }
  969.     i=smb_getmsghdr(&msg);
  970.     smb_unlockmsghdr(msg);
  971.     if(i) {
  972.         printf("smb_getmsghdr returned %d\n",i);
  973.         continue; }
  974.     for(m=0;m<datoffsets;m++)
  975.         if(msg.hdr.offset==datoffset[m].old)
  976.             break;
  977.     if(m<datoffsets) {                /* another index pointed to this data */
  978.         printf("duplicate index\n");
  979.         msg.hdr.offset=datoffset[m].new;
  980.         smb_incdat(datoffset[m].new,smb_getmsgdatlen(msg),1); }
  981.     else {
  982.  
  983.         datoffset[datoffsets].old=msg.hdr.offset;
  984.         fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
  985.  
  986.         datoffset[datoffsets].new=msg.hdr.offset
  987.             =smb_fallocdat(smb_getmsgdatlen(msg),1);
  988.         datoffsets++;
  989.  
  990.         /* Actually copy the data */
  991.  
  992.         fseek(tmp_sdt,msg.hdr.offset,SEEK_SET);
  993.         n=smb_datblocks(smb_getmsgdatlen(msg));
  994.         for(m=0;m<n;m++) {
  995.             fread(buf,1,SDT_BLOCK_LEN,sdt_fp);
  996.             fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); } }
  997.  
  998.     /* Write the new index entry */
  999.     msg.idx.offset=status.header_offset;
  1000.     length=smb_getmsghdrlen(msg);
  1001.     msg.idx.offset+=smb_fallochdr(length);
  1002.     fwrite(&msg.idx,1,sizeof(idxrec_t),tmp_sid);
  1003.  
  1004.     /* Write the new header entry */
  1005.     fseek(tmp_shd,msg.idx.offset,SEEK_SET);
  1006.     fwrite(&msg.hdr,1,sizeof(msghdr_t),tmp_shd);
  1007.     for(n=0;n<msg.hdr.total_dfields;n++)
  1008.         fwrite(&msg.dfield[n],1,sizeof(dfield_t),tmp_shd);
  1009.     for(n=0;n<msg.total_hfields;n++) {
  1010.         fwrite(&msg.hfield[n],1,sizeof(hfield_t),tmp_shd);
  1011.         fwrite(msg.hfield_dat[n],1,msg.hfield[n].length,tmp_shd); }
  1012.     while(length%SHD_BLOCK_LEN) {    /* pad with NULLs */
  1013.         fputc(0,tmp_shd);
  1014.         length++; }
  1015.     total++;
  1016.     smb_freemsgmem(msg); }
  1017.  
  1018. FREE(datoffset);
  1019. fclose(sha_fp);
  1020. fclose(sda_fp);
  1021.  
  1022. i=smb_trunchdr(10);
  1023. if(i) {
  1024.     printf("smb_trunchdr returned %d\n",i);
  1025.     smb_unlocksmbhdr();
  1026.     fclose(tmp_sdt);
  1027.     fclose(tmp_sid);
  1028.     fclose(tmp_shd);
  1029.     return; }
  1030. rewind(sid_fp);
  1031. chsize(fileno(sid_fp),0L);
  1032. fseek(tmp_sid,0L,SEEK_SET);
  1033. printf("\nCreating new index file...\n");
  1034. for(l=0;l<total;l++) {
  1035.     printf("%lu of %lu\r",l+1,total);
  1036.     if(!fread(&msg.idx,1,sizeof(idxrec_t),tmp_sid))
  1037.         break;
  1038.     if(msg.idx.attr&MSG_DELETE) {
  1039.         l--;
  1040.         continue; }
  1041.     if(!fwrite(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  1042.         break; }
  1043.  
  1044. fflush(sid_fp);
  1045. rewind(shd_fp);
  1046. chsize(fileno(shd_fp),0L);
  1047. fseek(tmp_shd,0,SEEK_SET);
  1048. for(l=0;l<status.header_offset;l++) {
  1049.     fread(&ch,1,1,tmp_shd);
  1050.     fwrite(&ch,1,1,shd_fp); }
  1051. printf("\nCreating new header file...\n");
  1052. for(l=0;;l++) {
  1053.     if(!fread(buf,1,SHD_BLOCK_LEN,tmp_shd))
  1054.         break;
  1055.     printf("%lu blocks\r",l+1);
  1056.     if(!fwrite(buf,1,SHD_BLOCK_LEN,shd_fp))
  1057.         break; }
  1058.  
  1059. fflush(shd_fp);
  1060. rewind(sdt_fp);
  1061. chsize(fileno(sdt_fp),0L);
  1062. fseek(tmp_sdt,0L,SEEK_SET);
  1063. printf("\nCreating new data file...\n");
  1064. for(l=0;;l++) {
  1065.     if(!fread(buf,1,SDT_BLOCK_LEN,tmp_sdt))
  1066.         break;
  1067.     printf("%lu blocks\r",l+1);
  1068.     if(!fwrite(buf,1,SDT_BLOCK_LEN,sdt_fp))
  1069.         break; }
  1070. fflush(sdt_fp);
  1071. fclose(tmp_sdt);
  1072. fclose(tmp_shd);
  1073. fclose(tmp_sid);
  1074. status.total_msgs=total;
  1075. if((i=smb_putstatus(status))!=0)
  1076.     printf("\nsmb_putstatus returned %d\n",i);
  1077. smb_unlocksmbhdr();
  1078. printf("\nDone.\n\n");
  1079. }
  1080.  
  1081.  
  1082. /****************************************************************************/
  1083. /* Read messages in message base                                            */
  1084. /****************************************************************************/
  1085. void readmsgs(ulong start)
  1086. {
  1087.     char    str[128];
  1088.     int     i,ch,done=0,domsg=1;
  1089.     ulong    l,count;
  1090.     smbmsg_t msg;
  1091.  
  1092. if(start)
  1093.     msg.offset=start-1;
  1094. else
  1095.     msg.offset=0;
  1096. while(!done) {
  1097.     if(domsg) {
  1098.         fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
  1099.         if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  1100.             break;
  1101.         i=smb_lockmsghdr(msg,10);
  1102.         if(i) {
  1103.             printf("smb_lockmsghdr returned %d\n",i);
  1104.             break; }
  1105.         i=smb_getmsghdr(&msg);
  1106.         if(i) {
  1107.             printf("smb_getmsghdr returned %d\n",i);
  1108.             break; }
  1109.  
  1110.         printf("\n%lu (%lu)\n",msg.hdr.number,msg.offset+1);
  1111.         printf("Subj : %s\n",msg.subj);
  1112.         printf("To   : %s",msg.to);
  1113.         if(msg.to_net.type)
  1114.             printf(" (%s)",msg.to_net.type==NET_FIDO
  1115.                 ? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
  1116.         printf("\nFrom : %s",msg.from);
  1117.         if(msg.from_net.type)
  1118.             printf(" (%s)",msg.from_net.type==NET_FIDO
  1119.                 ? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
  1120.                     : msg.from_net.addr);
  1121.         printf("\nDate : %.24s %s",ctime(&(time_t)msg.hdr.when_written.time)
  1122.             ,zonestr(msg.hdr.when_written.zone));
  1123.         printf("\n\n");
  1124.         for(i=0;i<msg.hdr.total_dfields;i++)
  1125.             switch(msg.dfield[i].type) {
  1126.                 case TEXT_BODY:
  1127.                 case TEXT_TAIL:
  1128.                     fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset+2
  1129.                         ,SEEK_SET);
  1130.                     for(l=2;l<msg.dfield[i].length;l++) {
  1131.                         ch=fgetc(sdt_fp);
  1132.                         if(ch)
  1133.                             putchar(ch); }
  1134.                     printf("\n");
  1135.                     break; }
  1136.         i=smb_unlockmsghdr(msg);
  1137.         if(i) {
  1138.             printf("smb_unlockmsghdr returned %d\n",i);
  1139.             break; }
  1140.         smb_freemsgmem(msg); }
  1141.     domsg=1;
  1142.     printf("\nReading %s (?=Menu): ",smb_file);
  1143.     switch(toupper(getch())) {
  1144.         case '?':
  1145.             printf("\n"
  1146.                    "\n"
  1147.                    "(R)e-read current message\n"
  1148.                    "(L)ist messages\n"
  1149.                    "(T)en more titles\n"
  1150.                    "(V)iew message headers\n"
  1151.                    "(Q)uit\n"
  1152.                    "(+/-) Forward/Backward\n"
  1153.                    "\n");
  1154.             domsg=0;
  1155.             break;
  1156.         case 'Q':
  1157.             printf("Quit\n");
  1158.             done=1;
  1159.             break;
  1160.         case 'R':
  1161.             printf("Re-read\n");
  1162.             break;
  1163.         case '-':
  1164.             printf("Backwards\n");
  1165.             if(msg.offset)
  1166.                 msg.offset--;
  1167.             break;
  1168.         case 'T':
  1169.             printf("Ten titles\n");
  1170.             listmsgs(msg.offset+2,10);
  1171.             msg.offset+=10;
  1172.             domsg=0;
  1173.             break;
  1174.         case 'L':
  1175.             printf("List messages\n");
  1176.             listmsgs(1,-1);
  1177.             domsg=0;
  1178.             break;
  1179.         case 'V':
  1180.             printf("View message headers\n");
  1181.             viewmsgs(1,-1);
  1182.             domsg=0;
  1183.             break;
  1184.         case CR:
  1185.         case '+':
  1186.             printf("Next\n");
  1187.             msg.offset++;
  1188.             break; } }
  1189. }
  1190.  
  1191. /***************/
  1192. /* Entry point */
  1193. /***************/
  1194. int main(int argc, char **argv)
  1195. {
  1196.     char cmd[128]="",*p,*s;
  1197.     int i,j,x,y;
  1198.     ulong l;
  1199.     smbstatus_t status;
  1200.  
  1201. smb_file[0]=0;
  1202. printf("\nSynchronet Message Base Utility v%s  "\
  1203.     "Copyright 1994 Digital Dynamics\n\n"
  1204.     ,SMBUTIL_VER);
  1205. for(x=1;x<argc;x++) {
  1206.     if(argv[x][0]=='/') {
  1207.         for(j=1;argv[x][j];j++)
  1208.             switch(toupper(argv[x][j])) {
  1209.                 case 'A':
  1210.                     mode|=NOANALYSIS;
  1211.                     break;
  1212.                 case 'F':   /* file attachment */
  1213.                     mode|=FAST;
  1214.                     break;
  1215.                 case 'D':
  1216.                     mode|=NOCRC;
  1217.                     break;
  1218.                 case 'Z':
  1219.                     if(isdigit(argv[x][j+1]))
  1220.                         tzone=atoi(argv[x]+j+1);
  1221.                     else if(!stricmp(argv[x]+j+1,"EST"))
  1222.                         tzone=EST;
  1223.                     else if(!stricmp(argv[x]+j+1,"EDT"))
  1224.                         tzone=EDT;
  1225.                     else if(!stricmp(argv[x]+j+1,"CST"))
  1226.                         tzone=CST;
  1227.                     else if(!stricmp(argv[x]+j+1,"CDT"))
  1228.                         tzone=CDT;
  1229.                     else if(!stricmp(argv[x]+j+1,"MST"))
  1230.                         tzone=MST;
  1231.                     else if(!stricmp(argv[x]+j+1,"MDT"))
  1232.                         tzone=MDT;
  1233.                     else if(!stricmp(argv[x]+j+1,"PST"))
  1234.                         tzone=PST;
  1235.                     else if(!stricmp(argv[x]+j+1,"PDT"))
  1236.                         tzone=PDT;
  1237.                     j=strlen(argv[x])-1;
  1238.                     break;
  1239.                 default:
  1240.                     printf("\nUnknown opt '%c'\n",argv[x][j]);
  1241.                 case '?':
  1242.                     printf("%s",usage);
  1243.                     exit(1);
  1244.                     break; } }
  1245.     else {
  1246.         if(!cmd[0])
  1247.             strcpy(cmd,argv[x]);
  1248.         else {
  1249.             sprintf(smb_file,"%.64s",argv[x]);
  1250.             p=strrchr(smb_file,'.');
  1251.             s=strrchr(smb_file,'\\');
  1252.             if(p>s) *p=0;
  1253.             strupr(smb_file);
  1254.             printf("Opening %s\r\n",smb_file);
  1255.             if((i=smb_open(10))!=0) {
  1256.                 printf("error %d opening %s message base\n",i,smb_file);
  1257.                 exit(1); }
  1258.             if(!filelength(fileno(shd_fp))) {
  1259.                 printf("Empty\n");
  1260.                 smb_close();
  1261.                 continue; }
  1262.             for(y=0;cmd[y];y++)
  1263.                 switch(toupper(cmd[y])) {
  1264.                     case 'I':
  1265.                         strcpy(filein,cmd+1);
  1266.                         i=smb_locksmbhdr(10);
  1267.                         if(i) {
  1268.                             printf("smb_locksmbhdr returned %d\n",i);
  1269.                             return(1); }
  1270.                         i=smb_getstatus(&status);
  1271.                         if(i) {
  1272.                             printf("smb_getstatus returned %d\n",i);
  1273.                             return(1); }
  1274.                             smb_unlocksmbhdr();
  1275.                         postmsg(status);
  1276.                         y=strlen(cmd)-1;
  1277.                         break;
  1278.                     case 'K':
  1279.                         printf("Killing %lu messages...\n",atol(cmd+1));
  1280.                         l=kill(atol(cmd+1));
  1281.                         printf("%lu messages killed.\n",l);
  1282.                         y=strlen(cmd)-1;
  1283.                         break;
  1284.                     case 'S':
  1285.                         showstatus();
  1286.                         break;
  1287.                     case 'C':
  1288.                         config();
  1289.                         break;
  1290.                     case 'L':
  1291.                         listmsgs(atol(cmd+1),-1L);
  1292.                         y=strlen(cmd)-1;
  1293.                         break;
  1294.                     case 'P':
  1295.                         packmsgs(atol(cmd+y+1));
  1296.                         y=strlen(cmd)-1;
  1297.                         break;
  1298.                     case 'R':
  1299.                         readmsgs(atol(cmd+1));
  1300.                         y=strlen(cmd)-1;
  1301.                         break;
  1302.                     case 'V':
  1303.                         viewmsgs(atol(cmd+1),-1L);
  1304.                         y=strlen(cmd)-1;
  1305.                         break;
  1306.                     case 'M':
  1307.                         maint();
  1308.                         break;
  1309.                     default:
  1310.                         printf("%s",usage);
  1311.                         break; }
  1312.             smb_close(); } } }
  1313. if(!cmd[0])
  1314.     printf("%s",usage);
  1315. return(0);
  1316. }
  1317.