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 >
Wrap
C/C++ Source or Header
|
1994-06-02
|
34KB
|
1,317 lines
/* SMBUTIL.C */
/* Synchronet Message Base Utility */
#define SMBUTIL_VER "1.11"
#include "smblib.h"
#include "smbutil.h"
#include "crc32.h"
extern long timezone=0; /* Fix for Borland C++ EST default */
extern int daylight=0; /* Fix for Borland C++ EDT default */
/********************/
/* Global variables */
/********************/
ulong mode=0L;
ushort tzone=PST;
char filein[128];
char attach[128];
/************************/
/* Program usage/syntax */
/************************/
char *usage=
"usage: smbutil [/opts] cmd <filespec.SHD>\n"
"\n"
"cmd:\n"
" l[n] = list msgs starting at number n\n"
" r[n] = read msgs starting at number n\n"
" v[n] = view msg headers starting at number n\n"
" k[n] = kill (delete) n msgs\n"
" i<f> = import from text file f\n"
" s = display msg base status\n"
" c = change msg base status\n"
" m = maintain msg base - delete old msgs and msgs over max\n"
" p[k] = pack msg base (k specifies minimum packable Kbytes)\n"
"opts:\n"
" a = always pack msg base (disable compression analysis)\n"
" f = fast msg creation mode\n"
" d = disable duplicate message checking\n"
" z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
;
/****************************************************************************/
/* Checks the disk drive for the existence of a file. Returns 1 if it */
/* exists, 0 if it doesn't. */
/****************************************************************************/
char fexist(char *filespec)
{
struct ffblk f;
if(findfirst(filespec,&f,0)==0)
return(1);
return(0);
}
/****************************************************************************/
/* Returns the length of the file in 'filespec' */
/****************************************************************************/
long flength(char *filespec)
{
struct ffblk f;
if(findfirst(filespec,&f,0)==0)
return(f.ff_fsize);
return(-1L);
}
/****************************************************************************/
/* Updates 16-bit "rcrc" with character 'ch' */
/****************************************************************************/
void ucrc16(uchar ch, ushort *rcrc) {
ushort i, cy;
uchar nch=ch;
for (i=0; i<8; i++) {
cy=*rcrc & 0x8000;
*rcrc<<=1;
if (nch & 0x80) *rcrc |= 1;
nch<<=1;
if (cy) *rcrc ^= 0x1021; }
}
/****************************************************************************/
/* Returns 16-crc of string (not counting terminating NULL) */
/****************************************************************************/
ushort crc16(char *str)
{
int i=0;
ushort crc=0;
ucrc16(0,&crc);
while(str[i])
ucrc16(str[i++],&crc);
ucrc16(0,&crc);
ucrc16(0,&crc);
return(crc);
}
/****************************************************************************/
/* Adds a new message to the message base */
/****************************************************************************/
void postmsg(smbstatus_t status)
{
char str[128],buf[SDT_BLOCK_LEN];
ushort xlat;
int i,j,k,file;
long length;
ulong offset,crc=0xffffffffUL;
FILE *instream;
smbmsg_t msg;
if(!filelength(fileno(shd_fp)))
smb_create(2000,2000,0,10);
length=flength(filein);
if(length<1L) {
printf("Invalid file size for '%s'\n",filein);
exit(1); }
length+=2; /* for translation string */
i=smb_open_da(10);
if(i) {
printf("smb_open_da returned %d\n",i);
exit(1); }
if(mode&FAST)
offset=smb_fallocdat(length,1);
else
offset=smb_allocdat(length,1);
fclose(sda_fp);
if((file=open(filein,O_RDONLY|O_BINARY))==-1
|| (instream=fdopen(file,"rb"))==NULL) {
printf("Error opening %s for read\n",filein);
smb_freemsgdat(offset,length,1);
exit(1); }
setvbuf(instream,NULL,_IOFBF,32*1024);
fseek(sdt_fp,offset,SEEK_SET);
xlat=XLAT_NONE;
fwrite(&xlat,2,1,sdt_fp);
k=SDT_BLOCK_LEN-2;
while(!feof(instream)) {
memset(buf,NULL,k);
j=fread(buf,1,k,instream);
if(!(mode&NOCRC)) {
for(i=0;i<j;i++)
crc=ucrc32(buf[i],crc); }
fwrite(buf,k,1,sdt_fp);
k=SDT_BLOCK_LEN; }
fclose(instream);
crc=~crc;
memset(&msg,0,sizeof(smbmsg_t));
memcpy(msg.hdr.id,"SHD\x1a",4);
msg.hdr.version=SMB_VERSION;
msg.hdr.when_written.time=time(NULL);
msg.hdr.when_written.zone=tzone;
if(!(mode&NOCRC)) {
i=smb_addcrc(status.max_crcs,crc,10);
if(i) {
printf("smb_addcrc returned %d\n",i);
smb_freemsgdat(offset,length,1);
exit(1); } }
msg.hdr.offset=offset;
printf("To: ");
gets(str);
i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
if(i) {
printf("smb_hfield returned %d\n",i);
smb_freemsgdat(offset,length,1);
exit(1); }
strlwr(str);
msg.idx.to=crc16(str);
printf("From: ");
gets(str);
i=smb_hfield(&msg,SENDER,strlen(str),str);
if(i) {
printf("smb_hfield returned %d\n",i);
smb_freemsgdat(offset,length,1);
exit(1); }
strlwr(str);
msg.idx.from=crc16(str);
printf("Subj: ");
gets(str);
i=smb_hfield(&msg,SUBJECT,strlen(str),str);
if(i) {
printf("smb_hfield returned %d\n",i);
smb_freemsgdat(offset,length,1);
exit(1); }
strlwr(str);
msg.idx.subj=crc16(str);
i=smb_dfield(&msg,TEXT_BODY,length);
if(i) {
printf("smb_dfield returned %d\n",i);
smb_freemsgdat(offset,length,1);
exit(1); }
i=smb_addmsghdr(&msg,&status,mode&FAST,10);
if(i) {
printf("smb_addmsghdr returned %d\n",i);
smb_freemsgdat(offset,length,1);
exit(1); }
smb_freemsgmem(msg);
}
/****************************************************************************/
/* Shows the message base header */
/****************************************************************************/
void showstatus()
{
int i;
smbstatus_t status;
i=smb_locksmbhdr(10);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return; }
i=smb_getstatus(&status);
smb_unlocksmbhdr();
if(i) {
printf("smb_getstatus returned %d\n",i);
return; }
printf("last_msg =%lu\n"
"total_msgs =%lu\n"
"header_offset =%lu\n"
"max_crcs =%lu\n"
"max_msgs =%lu\n"
"max_age =%u\n"
"reserved =%04Xh\n"
,status.last_msg
,status.total_msgs
,status.header_offset
,status.max_crcs
,status.max_msgs
,status.max_age
,status.reserved
);
}
/****************************************************************************/
/* Configure message base header */
/****************************************************************************/
void config()
{
char max_msgs[128],max_crcs[128],max_age[128];
int i;
smbstatus_t status;
i=smb_locksmbhdr(10);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return; }
i=smb_getstatus(&status);
smb_unlocksmbhdr();
if(i) {
printf("smb_getstatus returned %d\n",i);
return; }
printf("Max msgs =%-5lu New value (CR=No Change): ",status.max_msgs);
gets(max_msgs);
printf("Max crcs =%-5lu New value (CR=No Change): ",status.max_crcs);
gets(max_crcs);
printf("Max age =%-5u New value (CR=No Change): ",status.max_age);
gets(max_age);
i=smb_locksmbhdr(10);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return; }
i=smb_getstatus(&status);
if(i) {
printf("smb_getstatus returned %d\n",i);
smb_unlocksmbhdr();
return; }
if(isdigit(max_msgs[0]))
status.max_msgs=atol(max_msgs);
if(isdigit(max_crcs[0]))
status.max_crcs=atol(max_crcs);
if(isdigit(max_age[0]))
status.max_age=atoi(max_age);
i=smb_putstatus(status);
smb_unlocksmbhdr();
if(i)
printf("smb_putstatus returned %d\n",i);
}
/****************************************************************************/
/* Lists messages' to, from, and subject */
/****************************************************************************/
void listmsgs(ulong start, ulong count)
{
int i;
ulong l=0;
smbmsg_t msg;
idxrec_t idxrec;
if(!start)
start=1;
fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
while(l<count) {
if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
break;
i=smb_lockmsghdr(msg,10);
if(i) {
printf("smb_lockmsghdr returned %d\n",i);
break; }
i=smb_getmsghdr(&msg);
smb_unlockmsghdr(msg);
if(i) {
printf("smb_getmsghdr returned %d\n",i);
break; }
printf("%4lu %-25.25s %-25.25s %.20s\n"
,msg.hdr.number,msg.from,msg.to,msg.subj);
smb_freemsgmem(msg);
l++; }
}
/****************************************************************************/
/* Returns an ASCII string for FidoNet address 'addr' */
/****************************************************************************/
char *faddrtoa(fidoaddr_t addr)
{
static char str[25];
char point[25];
sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
if(addr.point) {
sprintf(point,".%u",addr.point);
strcat(str,point); }
return(str);
}
char *binstr(uchar *buf, ushort length)
{
static char str[128];
char tmp[128];
int i;
str[0]=0;
for(i=0;i<length;i++)
if(buf[i] && (buf[i]<SP || buf[i]>=0x7f))
break;
if(i==length) /* not binary */
return(buf);
for(i=0;i<length;i++) {
sprintf(tmp,"%02X ",buf[i]);
strcat(str,tmp); }
return(str);
}
/****************************************************************************/
/* Converts when_t.zone into ASCII format */
/****************************************************************************/
char *zonestr(short zone)
{
static char str[32];
switch(zone) {
case 0: return("UT");
case AST: return("AST");
case EST: return("EST");
case CST: return("CST");
case MST: return("MST");
case PST: return("PST");
case YST: return("YST");
case HST: return("HST");
case BST: return("BST");
case ADT: return("ADT");
case EDT: return("EDT");
case CDT: return("CDT");
case MDT: return("MDT");
case PDT: return("PDT");
case YDT: return("YDT");
case HDT: return("HDT");
case BDT: return("BDT");
case MID: return("MID");
case VAN: return("VAN");
case EDM: return("EDM");
case WIN: return("WIN");
case BOG: return("BOG");
case CAR: return("CAR");
case RIO: return("RIO");
case FER: return("FER");
case AZO: return("AZO");
case LON: return("LON");
case BER: return("BER");
case ATH: return("ATH");
case MOS: return("MOS");
case DUB: return("DUB");
case KAB: return("KAB");
case KAR: return("KAR");
case BOM: return("BOM");
case KAT: return("KAT");
case DHA: return("DHA");
case BAN: return("BAN");
case HON: return("HON");
case TOK: return("TOK");
case SYD: return("SYD");
case NOU: return("NOU");
case WEL: return("WEL");
}
sprintf(str,"%02d:%02d",zone/60,zone<0 ? (-zone)%60 : zone%60);
return(str);
}
/****************************************************************************/
/* Displays message header information */
/****************************************************************************/
void viewmsgs(ulong start, ulong count)
{
char when_written[128]
,when_imported[128];
int i;
ulong l=0;
smbmsg_t msg;
idxrec_t idxrec;
if(!start)
start=1;
fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
while(l<count) {
if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
break;
i=smb_lockmsghdr(msg,10);
if(i) {
printf("smb_lockmsghdr returned %d\n",i);
break; }
i=smb_getmsghdr(&msg);
smb_unlockmsghdr(msg);
if(i) {
printf("smb_getmsghdr returned %d\n",i);
break; }
sprintf(when_written,"%.24s %s"
,ctime((time_t *)&msg.hdr.when_written.time)
,zonestr(msg.hdr.when_written.zone));
sprintf(when_imported,"%.24s %s"
,ctime((time_t *)&msg.hdr.when_imported.time)
,zonestr(msg.hdr.when_imported.zone));
printf( "%-20.20s %s\n"
"%-20.20s %s\n"
"%-20.20s %s\n"
"%-20.20s %04Xh\n"
"%-20.20s %04Xh\n"
"%-20.20s %u\n"
"%-20.20s %04Xh\n"
"%-20.20s %08lXh\n"
"%-20.20s %08lXh\n"
"%-20.20s %s\n"
"%-20.20s %s\n"
"%-20.20s %ld\n"
"%-20.20s %ld\n"
"%-20.20s %ld\n"
"%-20.20s %ld\n"
"%-20.20s %s\n"
"%-20.20s %ld\n"
"%-20.20s %u\n",
"subj",
msg.subj,
"from",
msg.from,
"to",
msg.to,
"type",
msg.hdr.type,
"version",
msg.hdr.version,
"length",
msg.hdr.length,
"attr",
msg.hdr.attr,
"auxattr",
msg.hdr.auxattr,
"netattr",
msg.hdr.netattr,
"when_written",
when_written,
"when_imported",
when_imported,
"number",
msg.hdr.number,
"thread_orig",
msg.hdr.thread_orig,
"thread_next",
msg.hdr.thread_next,
"thread_first",
msg.hdr.thread_first,
"reserved[16]",
binstr(msg.hdr.reserved,16),
"offset",
msg.hdr.offset,
"total_dfields",
msg.hdr.total_dfields
);
for(i=0;i<msg.hdr.total_dfields;i++)
printf("dfield[%u].type %02Xh\n"
"dfield[%u].offset %lu\n"
"dfield[%u].length %d\n"
,i,msg.dfield[i].type
,i,msg.dfield[i].offset
,i,msg.dfield[i].length);
for(i=0;i<msg.total_hfields;i++)
printf("hfield[%u].type %02Xh\n"
"hfield[%u].length %d\n"
"hfield[%u]_dat %s\n"
,i,msg.hfield[i].type
,i,msg.hfield[i].length
,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
if(msg.from_net.type)
printf("from_net.type %02Xh\n"
"from_net.addr %s\n"
,msg.from_net.type
,msg.from_net.type==NET_FIDO
? faddrtoa(*(fidoaddr_t *)msg.from_net.addr) : msg.from_net.addr);
if(msg.to_net.type)
printf("to_net.type %02Xh\n"
"to_net.addr %s\n"
,msg.to_net.type
,msg.to_net.type==NET_FIDO
? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
if(msg.replyto_net.type)
printf("replyto_net.type %02Xh\n"
"replyto_net.addr %s\n"
,msg.replyto_net.type
,msg.replyto_net.type==NET_FIDO
? faddrtoa(*(fidoaddr_t *)msg.replyto_net.addr)
: msg.replyto_net.addr);
printf("from_agent %02Xh\n"
"to_agent %02Xh\n"
"replyto_agent %02Xh\n"
,msg.from_agent
,msg.to_agent
,msg.replyto_agent);
printf("\n");
smb_freemsgmem(msg);
l++; }
}
/****************************************************************************/
/* Maintain message base - deletes messages older than max age (in days) */
/* or messages that exceed maximum */
/****************************************************************************/
void maint(void)
{
int i;
ulong l,m,n,f,flagged=0;
time_t now;
smbstatus_t status;
smbmsg_t msg;
idxrec_t huge *idx;
printf("Maintaining message base...\r\n");
now=time(NULL);
i=smb_locksmbhdr(10);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return; }
i=smb_getstatus(&status);
if(i) {
smb_unlocksmbhdr();
printf("smb_getstatus returned %d\n",i);
return; }
if(!status.total_msgs) {
smb_unlocksmbhdr();
printf("Empty\n");
return; }
printf("Loading index...\n");
if((idx=(idxrec_t *)MALLOC(sizeof(idxrec_t)*status.total_msgs))
==NULL) {
smb_unlocksmbhdr();
printf("can't allocate %lu bytes of memory\n"
,sizeof(idxrec_t)*status.total_msgs);
return; }
fseek(sid_fp,0L,SEEK_SET);
for(l=0;l<status.total_msgs;l++) {
printf("%lu of %lu\r"
,l+1,status.total_msgs);
if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
break; }
printf("\nDone.\n\n");
if(status.max_age) {
printf("Scanning for messages more than %u days old...\n"
,status.max_age);
for(m=0;m<l;m++) {
printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
if(idx[m].attr&MSG_PERMANENT)
continue;
if((now-idx[m].time)/(24L*60L*60L)>status.max_age) {
flagged++;
idx[m].attr|=MSG_DELETE; } } /* mark for deletion */
printf("\r100%% (%lu flagged for deletion)\n",flagged); }
printf("Scanning for read messages to be killed...\n");
for(m=f=0;m<l;m++) {
printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
continue;
if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
f++;
flagged++;
idx[m].attr|=MSG_DELETE; } }
printf("\r100%% (%lu flagged for deletion)\n",f);
if(l-flagged>status.max_msgs) {
printf("Flagging excess messages for deletion...\n");
for(m=n=0,f=flagged;l-flagged>status.max_msgs && m<l;m++) {
if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
continue;
printf("%lu of %lu\r",++n,(l-f)-status.max_msgs);
flagged++;
idx[m].attr|=MSG_DELETE; } /* mark for deletion */
printf("\nDone.\n\n"); }
if(!flagged) { /* No messages to delete */
FREE(idx);
smb_unlocksmbhdr();
return; }
printf("Freeing allocated header and data blocks for deleted messages...\n");
i=smb_open_da(10);
if(i) {
smb_unlocksmbhdr();
printf("smb_open_da returned %d\n",i);
exit(1); }
i=smb_open_ha(10);
if(i) {
smb_unlocksmbhdr();
printf("smb_open_ha returned %d\n",i);
exit(1); }
for(m=n=0;m<l;m++) {
if(idx[m].attr&MSG_DELETE) {
printf("%lu of %lu\r",++n,flagged);
msg.idx=idx[m];
msg.hdr.number=msg.idx.number;
if((i=smb_getmsgidx(&msg))!=0) {
smb_unlockmsghdr(msg);
printf("\nsmb_getmsgidx returned %d\n",i);
break; }
i=smb_lockmsghdr(msg,10);
if(i) {
printf("\nsmb_lockmsghdr returned %d\n",i);
break; }
if((i=smb_getmsghdr(&msg))!=0) {
smb_unlockmsghdr(msg);
printf("\nsmb_getmsghdr returned %d\n",i);
break; }
msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */
if((i=smb_putmsg(msg))!=0) {
smb_freemsgmem(msg);
smb_unlockmsghdr(msg);
printf("\nsmb_putmsg returned %d\n",i);
break; }
smb_unlockmsghdr(msg);
if((i=smb_freemsg(msg,status))!=0) {
smb_freemsgmem(msg);
printf("\nsmb_freemsg returned %d\n",i);
break; }
smb_freemsgmem(msg); } }
fclose(sha_fp);
fclose(sda_fp);
printf("\nDone.\n\n");
printf("Re-writing index...\n");
rewind(sid_fp);
if(chsize(fileno(sid_fp),0L))
printf("chsize failed!\n");
for(m=n=0;m<l;m++) {
if(idx[m].attr&MSG_DELETE)
continue;
printf("%lu of %lu\r",++n,l-flagged);
fwrite(&idx[m],sizeof(idxrec_t),1,sid_fp); }
printf("\nDone.\n\n");
fflush(sid_fp);
FREE(idx);
status.total_msgs-=flagged;
smb_putstatus(status);
smb_unlocksmbhdr();
}
/****************************************************************************/
/* Kills 'msgs' number of messags */
/* Returns actual number of messages killed. */
/****************************************************************************/
ulong kill(ulong msgs)
{
int i;
ulong l,m,n,flagged=0;
smbstatus_t status;
smbmsg_t msg;
idxrec_t *idx;
i=smb_locksmbhdr(10);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return(0); }
i=smb_getstatus(&status);
if(i) {
smb_unlocksmbhdr();
printf("smb_getstatus returned %d\n",i);
return(0); }
printf("Loading index...\n");
if((idx=(idxrec_t *)MALLOC(sizeof(idxrec_t)*status.total_msgs))
==NULL) {
smb_unlocksmbhdr();
printf("can't allocate %lu bytes of memory\n"
,sizeof(idxrec_t)*status.total_msgs);
return(0); }
fseek(sid_fp,0L,SEEK_SET);
for(l=0;l<status.total_msgs;l++) {
printf("%lu of %lu\r"
,l+1,status.total_msgs);
if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
break; }
printf("\nDone.\n\n");
printf("Flagging messages for deletion...\n");
for(m=0;m<l && flagged<msgs;m++) {
if(idx[m].attr&(MSG_PERMANENT))
continue;
printf("%lu of %lu\r",++flagged,msgs);
idx[m].attr|=MSG_DELETE; } /* mark for deletion */
printf("\nDone.\n\n");
printf("Freeing allocated header and data blocks for deleted messages...\n");
i=smb_open_da(10);
if(i) {
smb_unlocksmbhdr();
printf("smb_open_da returned %d\n",i);
exit(1); }
i=smb_open_ha(10);
if(i) {
smb_unlocksmbhdr();
printf("smb_open_ha returned %d\n",i);
exit(1); }
for(m=n=0;m<l;m++) {
if(idx[m].attr&MSG_DELETE) {
printf("%lu of %lu\r",++n,flagged);
msg.idx=idx[m];
i=smb_lockmsghdr(msg,10);
if(i) {
printf("\nsmb_lockmsghdr returned %d\n",i);
break; }
msg.hdr.number=msg.idx.number;
if((i=smb_getmsgidx(&msg))!=0) {
smb_unlockmsghdr(msg);
printf("\nsmb_getmsgidx returned %d\n",i);
break; }
if((i=smb_getmsghdr(&msg))!=0) {
smb_unlockmsghdr(msg);
printf("\nsmb_getmsghdr returned %d\n",i);
break; }
msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */
if((i=smb_putmsg(msg))!=0) {
smb_unlockmsghdr(msg);
printf("\nsmb_putmsg returned %d\n",i);
break; }
smb_unlockmsghdr(msg);
smb_freemsg(msg,status);
smb_freemsgmem(msg); } }
fclose(sha_fp);
fclose(sda_fp);
printf("\nDone.\n\n");
printf("Re-writing index...\n");
rewind(sid_fp);
chsize(fileno(sid_fp),0L);
for(m=n=0;m<l;m++) {
if(idx[m].attr&MSG_DELETE)
continue;
printf("%lu of %lu\r",++n,l-flagged);
fwrite(&idx[m],1,sizeof(idxrec_t),sid_fp); }
printf("\nDone.\n\n");
fflush(sid_fp);
FREE(idx);
status.total_msgs-=flagged;
smb_putstatus(status);
smb_unlocksmbhdr();
return(flagged);
}
typedef struct {
ulong old,new;
} datoffset_t;
/****************************************************************************/
/* Removes all unused blocks from SDT and SHD files */
/****************************************************************************/
void packmsgs(ulong packable)
{
uchar buf[SDT_BLOCK_LEN],ch;
int i,file;
ulong l,m,n,datoffsets=0,length,total=0;
FILE *tmp_sdt,*tmp_shd,*tmp_sid;
smbhdr_t hdr;
smbstatus_t status;
smbmsg_t msg;
datoffset_t *datoffset;
printf("Packing message base...\n");
i=smb_locksmbhdr(10);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return; }
i=smb_getstatus(&status);
if(i) {
smb_unlocksmbhdr();
printf("smb_getstatus returned %d\n",i);
return; }
i=smb_open_ha(10);
if(i) {
smb_unlocksmbhdr();
printf("smb_open_ha returned %d\n",i);
return; }
i=smb_open_da(10);
if(i) {
smb_unlocksmbhdr();
fclose(sha_fp);
printf("smb_open_da returned %d\n",i);
return; }
if(!status.total_msgs) {
printf("Empty\n");
rewind(shd_fp);
chsize(fileno(shd_fp),status.header_offset);
rewind(sdt_fp);
chsize(fileno(sdt_fp),0L);
rewind(sid_fp);
chsize(fileno(sid_fp),0L);
rewind(sha_fp);
chsize(fileno(sha_fp),0L);
rewind(sda_fp);
chsize(fileno(sda_fp),0L);
fclose(sha_fp);
fclose(sda_fp);
smb_unlocksmbhdr();
return; }
if(!(mode&NOANALYSIS)) {
printf("Analyzing data blocks...\n");
length=filelength(fileno(sda_fp));
fseek(sda_fp,0L,SEEK_SET);
for(l=m=0;l<length;l+=2) {
printf("\r%2u%% ",l ? (long)(100.0/((float)length/l)) : 0);
i=0;
if(!fread(&i,2,1,sda_fp))
break;
if(!i)
m++; }
printf("\rAnalyzing header blocks...\n");
length=filelength(fileno(sha_fp));
fseek(sha_fp,0L,SEEK_SET);
for(l=n=0;l<length;l++) {
printf("\r%2u%% ",l ? (long)(100.0/((float)length/l)) : 0);
ch=0;
if(!fread(&ch,1,1,sha_fp))
break;
if(!ch)
n++; }
if(!m && !n) {
printf("\rAlready compressed.\n\n");
fclose(sha_fp);
fclose(sda_fp);
smb_unlocksmbhdr();
return; }
if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
printf("\rLess than %luk compressable bytes.\n\n",packable);
fclose(sha_fp);
fclose(sda_fp);
smb_unlocksmbhdr();
return; }
printf("\rCompressing %lu data blocks (%lu bytes)\n"
" and %lu header blocks (%lu bytes)\n"
,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN); }
rewind(sha_fp);
chsize(fileno(sha_fp),0L); /* Reset both allocation tables */
rewind(sda_fp);
chsize(fileno(sda_fp),0L);
tmp_sdt=tmpfile();
tmp_shd=tmpfile();
tmp_sid=tmpfile();
if(!tmp_sdt || !tmp_shd || !tmp_sid) {
smb_unlocksmbhdr();
fclose(sha_fp);
fclose(sda_fp);
printf("error opening temp file\n");
return; }
setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
if((datoffset=(datoffset_t *)MALLOC(sizeof(datoffset_t)*status.total_msgs))
==NULL) {
smb_unlocksmbhdr();
fclose(sha_fp);
fclose(sda_fp);
fclose(tmp_sdt);
fclose(tmp_shd);
fclose(tmp_sid);
printf("error allocating mem\n");
return; }
fseek(shd_fp,0L,SEEK_SET);
fread(&hdr,1,sizeof(smbhdr_t),shd_fp);
fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
fwrite(&status,1,sizeof(smbstatus_t),tmp_shd);
for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<status.header_offset;l++) {
fread(&ch,1,1,shd_fp); /* copy additional base header records */
fwrite(&ch,1,1,tmp_shd); }
fseek(sid_fp,0L,SEEK_SET);
for(l=0;l<status.total_msgs;l++) {
printf("%lu of %lu\r",l+1,status.total_msgs);
if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
break;
if(msg.idx.attr&MSG_DELETE) {
printf("\nDeleted.\n");
continue; }
i=smb_lockmsghdr(msg,10);
if(i) {
printf("smb_lockmsghdr returned %d\n",i);
continue; }
i=smb_getmsghdr(&msg);
smb_unlockmsghdr(msg);
if(i) {
printf("smb_getmsghdr returned %d\n",i);
continue; }
for(m=0;m<datoffsets;m++)
if(msg.hdr.offset==datoffset[m].old)
break;
if(m<datoffsets) { /* another index pointed to this data */
printf("duplicate index\n");
msg.hdr.offset=datoffset[m].new;
smb_incdat(datoffset[m].new,smb_getmsgdatlen(msg),1); }
else {
datoffset[datoffsets].old=msg.hdr.offset;
fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
datoffset[datoffsets].new=msg.hdr.offset
=smb_fallocdat(smb_getmsgdatlen(msg),1);
datoffsets++;
/* Actually copy the data */
fseek(tmp_sdt,msg.hdr.offset,SEEK_SET);
n=smb_datblocks(smb_getmsgdatlen(msg));
for(m=0;m<n;m++) {
fread(buf,1,SDT_BLOCK_LEN,sdt_fp);
fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); } }
/* Write the new index entry */
msg.idx.offset=status.header_offset;
length=smb_getmsghdrlen(msg);
msg.idx.offset+=smb_fallochdr(length);
fwrite(&msg.idx,1,sizeof(idxrec_t),tmp_sid);
/* Write the new header entry */
fseek(tmp_shd,msg.idx.offset,SEEK_SET);
fwrite(&msg.hdr,1,sizeof(msghdr_t),tmp_shd);
for(n=0;n<msg.hdr.total_dfields;n++)
fwrite(&msg.dfield[n],1,sizeof(dfield_t),tmp_shd);
for(n=0;n<msg.total_hfields;n++) {
fwrite(&msg.hfield[n],1,sizeof(hfield_t),tmp_shd);
fwrite(msg.hfield_dat[n],1,msg.hfield[n].length,tmp_shd); }
while(length%SHD_BLOCK_LEN) { /* pad with NULLs */
fputc(0,tmp_shd);
length++; }
total++;
smb_freemsgmem(msg); }
FREE(datoffset);
fclose(sha_fp);
fclose(sda_fp);
i=smb_trunchdr(10);
if(i) {
printf("smb_trunchdr returned %d\n",i);
smb_unlocksmbhdr();
fclose(tmp_sdt);
fclose(tmp_sid);
fclose(tmp_shd);
return; }
rewind(sid_fp);
chsize(fileno(sid_fp),0L);
fseek(tmp_sid,0L,SEEK_SET);
printf("\nCreating new index file...\n");
for(l=0;l<total;l++) {
printf("%lu of %lu\r",l+1,total);
if(!fread(&msg.idx,1,sizeof(idxrec_t),tmp_sid))
break;
if(msg.idx.attr&MSG_DELETE) {
l--;
continue; }
if(!fwrite(&msg.idx,1,sizeof(idxrec_t),sid_fp))
break; }
fflush(sid_fp);
rewind(shd_fp);
chsize(fileno(shd_fp),0L);
fseek(tmp_shd,0,SEEK_SET);
for(l=0;l<status.header_offset;l++) {
fread(&ch,1,1,tmp_shd);
fwrite(&ch,1,1,shd_fp); }
printf("\nCreating new header file...\n");
for(l=0;;l++) {
if(!fread(buf,1,SHD_BLOCK_LEN,tmp_shd))
break;
printf("%lu blocks\r",l+1);
if(!fwrite(buf,1,SHD_BLOCK_LEN,shd_fp))
break; }
fflush(shd_fp);
rewind(sdt_fp);
chsize(fileno(sdt_fp),0L);
fseek(tmp_sdt,0L,SEEK_SET);
printf("\nCreating new data file...\n");
for(l=0;;l++) {
if(!fread(buf,1,SDT_BLOCK_LEN,tmp_sdt))
break;
printf("%lu blocks\r",l+1);
if(!fwrite(buf,1,SDT_BLOCK_LEN,sdt_fp))
break; }
fflush(sdt_fp);
fclose(tmp_sdt);
fclose(tmp_shd);
fclose(tmp_sid);
status.total_msgs=total;
if((i=smb_putstatus(status))!=0)
printf("\nsmb_putstatus returned %d\n",i);
smb_unlocksmbhdr();
printf("\nDone.\n\n");
}
/****************************************************************************/
/* Read messages in message base */
/****************************************************************************/
void readmsgs(ulong start)
{
char str[128];
int i,ch,done=0,domsg=1;
ulong l,count;
smbmsg_t msg;
if(start)
msg.offset=start-1;
else
msg.offset=0;
while(!done) {
if(domsg) {
fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
break;
i=smb_lockmsghdr(msg,10);
if(i) {
printf("smb_lockmsghdr returned %d\n",i);
break; }
i=smb_getmsghdr(&msg);
if(i) {
printf("smb_getmsghdr returned %d\n",i);
break; }
printf("\n%lu (%lu)\n",msg.hdr.number,msg.offset+1);
printf("Subj : %s\n",msg.subj);
printf("To : %s",msg.to);
if(msg.to_net.type)
printf(" (%s)",msg.to_net.type==NET_FIDO
? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
printf("\nFrom : %s",msg.from);
if(msg.from_net.type)
printf(" (%s)",msg.from_net.type==NET_FIDO
? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
: msg.from_net.addr);
printf("\nDate : %.24s %s",ctime(&(time_t)msg.hdr.when_written.time)
,zonestr(msg.hdr.when_written.zone));
printf("\n\n");
for(i=0;i<msg.hdr.total_dfields;i++)
switch(msg.dfield[i].type) {
case TEXT_BODY:
case TEXT_TAIL:
fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset+2
,SEEK_SET);
for(l=2;l<msg.dfield[i].length;l++) {
ch=fgetc(sdt_fp);
if(ch)
putchar(ch); }
printf("\n");
break; }
i=smb_unlockmsghdr(msg);
if(i) {
printf("smb_unlockmsghdr returned %d\n",i);
break; }
smb_freemsgmem(msg); }
domsg=1;
printf("\nReading %s (?=Menu): ",smb_file);
switch(toupper(getch())) {
case '?':
printf("\n"
"\n"
"(R)e-read current message\n"
"(L)ist messages\n"
"(T)en more titles\n"
"(V)iew message headers\n"
"(Q)uit\n"
"(+/-) Forward/Backward\n"
"\n");
domsg=0;
break;
case 'Q':
printf("Quit\n");
done=1;
break;
case 'R':
printf("Re-read\n");
break;
case '-':
printf("Backwards\n");
if(msg.offset)
msg.offset--;
break;
case 'T':
printf("Ten titles\n");
listmsgs(msg.offset+2,10);
msg.offset+=10;
domsg=0;
break;
case 'L':
printf("List messages\n");
listmsgs(1,-1);
domsg=0;
break;
case 'V':
printf("View message headers\n");
viewmsgs(1,-1);
domsg=0;
break;
case CR:
case '+':
printf("Next\n");
msg.offset++;
break; } }
}
/***************/
/* Entry point */
/***************/
int main(int argc, char **argv)
{
char cmd[128]="",*p,*s;
int i,j,x,y;
ulong l;
smbstatus_t status;
smb_file[0]=0;
printf("\nSynchronet Message Base Utility v%s "\
"Copyright 1994 Digital Dynamics\n\n"
,SMBUTIL_VER);
for(x=1;x<argc;x++) {
if(argv[x][0]=='/') {
for(j=1;argv[x][j];j++)
switch(toupper(argv[x][j])) {
case 'A':
mode|=NOANALYSIS;
break;
case 'F': /* file attachment */
mode|=FAST;
break;
case 'D':
mode|=NOCRC;
break;
case 'Z':
if(isdigit(argv[x][j+1]))
tzone=atoi(argv[x]+j+1);
else if(!stricmp(argv[x]+j+1,"EST"))
tzone=EST;
else if(!stricmp(argv[x]+j+1,"EDT"))
tzone=EDT;
else if(!stricmp(argv[x]+j+1,"CST"))
tzone=CST;
else if(!stricmp(argv[x]+j+1,"CDT"))
tzone=CDT;
else if(!stricmp(argv[x]+j+1,"MST"))
tzone=MST;
else if(!stricmp(argv[x]+j+1,"MDT"))
tzone=MDT;
else if(!stricmp(argv[x]+j+1,"PST"))
tzone=PST;
else if(!stricmp(argv[x]+j+1,"PDT"))
tzone=PDT;
j=strlen(argv[x])-1;
break;
default:
printf("\nUnknown opt '%c'\n",argv[x][j]);
case '?':
printf("%s",usage);
exit(1);
break; } }
else {
if(!cmd[0])
strcpy(cmd,argv[x]);
else {
sprintf(smb_file,"%.64s",argv[x]);
p=strrchr(smb_file,'.');
s=strrchr(smb_file,'\\');
if(p>s) *p=0;
strupr(smb_file);
printf("Opening %s\r\n",smb_file);
if((i=smb_open(10))!=0) {
printf("error %d opening %s message base\n",i,smb_file);
exit(1); }
if(!filelength(fileno(shd_fp))) {
printf("Empty\n");
smb_close();
continue; }
for(y=0;cmd[y];y++)
switch(toupper(cmd[y])) {
case 'I':
strcpy(filein,cmd+1);
i=smb_locksmbhdr(10);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return(1); }
i=smb_getstatus(&status);
if(i) {
printf("smb_getstatus returned %d\n",i);
return(1); }
smb_unlocksmbhdr();
postmsg(status);
y=strlen(cmd)-1;
break;
case 'K':
printf("Killing %lu messages...\n",atol(cmd+1));
l=kill(atol(cmd+1));
printf("%lu messages killed.\n",l);
y=strlen(cmd)-1;
break;
case 'S':
showstatus();
break;
case 'C':
config();
break;
case 'L':
listmsgs(atol(cmd+1),-1L);
y=strlen(cmd)-1;
break;
case 'P':
packmsgs(atol(cmd+y+1));
y=strlen(cmd)-1;
break;
case 'R':
readmsgs(atol(cmd+1));
y=strlen(cmd)-1;
break;
case 'V':
viewmsgs(atol(cmd+1),-1L);
y=strlen(cmd)-1;
break;
case 'M':
maint();
break;
default:
printf("%s",usage);
break; }
smb_close(); } } }
if(!cmd[0])
printf("%s",usage);
return(0);
}