smbutil.c 41.97 KiB
/* smbutil.c */
/* Synchronet message base (SMB) utility */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#define SMBUTIL_VER "2.30"
#define NOANALYSIS (1L<<0)
#ifdef __WATCOMC__
#define ffblk find_t
#define findfirst(x,y,z) _dos_findfirst(x,z,y)
#define findnext(x) _dos_findnext(x)
#endif
#if defined(_WIN32)
#include <ctype.h> /* isdigit() */
#include <conio.h> /* getch() */
#endif
/* ANSI */
#include <stdio.h>
#include <time.h> /* time */
#include <errno.h> /* errno */
#include <string.h> /* strrchr */
#include "smbwrap.h"
#include "smblib.h"
#include "crc32.h"
#ifdef __WATCOMC__
#include <dos.h>
#endif
/* gets is dangerous */
#define gets(str) fgets((str), sizeof(str) - 1, stdin)
/********************/
/* Global variables */
/********************/
smb_t smb;
ulong mode=0L;
ushort tzone=PST;
/************************/
/* 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"
" i[f] = import msg from text file f (or use stdin)\n"
" e[f] = import e-mail from text file f (or use stdin)\n"
" n[f] = import netmail from text file f (or use stdin)\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"
" c = create message base if it doesn't exist\n"
" a = always pack msg base (disable compression analysis)\n"
" t<s> = set 'to' user name for imported message\n"
" n<s> = set 'to' netmail address for imported message\n"
" u<s> = set 'to' user number for imported message\n"
" f<s> = set 'from' user name for imported message\n"
" e<s> = set 'from' user number for imported message\n"
" s<s> = set 'subject' for imported message\n"
" z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
;
char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
,"Jul","Aug","Sep","Oct","Nov","Dec"};
/****************************************************************************/
/* 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 CRC-16 of string (not including 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);
}
void remove_re(char *str)
{
while(!strnicmp(str,"RE:",3)) {
strcpy(str,str+3);
while(str[0]==SP)
strcpy(str,str+1);
}
}
/************************************************/
/* Truncates white-space chars off end of 'str' */
/************************************************/
static void truncsp(char *str)
{
uint c;
c=strlen(str);
while(c && (uchar)str[c-1]<=' ') c--;
str[c]=0;
}
/****************************************************************************/
/* Adds a new message to the message base */
/****************************************************************************/
void postmsg(char type, char* to, char* to_number, char* to_address,
char* from, char* from_number, char* subject, FILE* fp)
{
char str[128];
char buf[128];
char pad=0;
char* msgtxt=NULL;
long msgtxtlen;
ushort xlat,net;
int i;
long l,length;
ulong offset,crc;
smbmsg_t msg;
/* Read message text from stream (file or stdin) */
msgtxtlen=0;
while(!feof(fp)) {
i=fread(buf,1,sizeof(buf),fp);
if(i<1)
break;
if((msgtxt=(char*)realloc(msgtxt,msgtxtlen+i))==NULL) {
fprintf(stderr,"\n\7malloc(%ld) failure\n",msgtxtlen+i);
exit(1);
}
memcpy(msgtxt+msgtxtlen,buf,i);
msgtxtlen+=i;
}
/* Allocate space in message base */
length=msgtxtlen+sizeof(xlat); /* for translation string */
if(!(smb.status.attr&SMB_HYPERALLOC)) {
i=smb_open_da(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_open_da returned %d: %s\n",i,smb.last_error);
exit(1);
}
offset=smb_allocdat(&smb,length,1);
smb_close_da(&smb);
} else
offset=smb_hallocdat(&smb);
fseek(smb.sdt_fp,offset,SEEK_SET);
xlat=XLAT_NONE;
smb_fwrite(&xlat,sizeof(xlat),smb.sdt_fp);
smb_fwrite(msgtxt,msgtxtlen,smb.sdt_fp);
for(l=length;l%SDT_BLOCK_LEN;l++)
smb_fwrite(&pad,1,smb.sdt_fp);
fflush(smb.sdt_fp);
memset(&msg,0,sizeof(smbmsg_t));
memcpy(msg.hdr.id,"SHD\x1a",4);
msg.hdr.version=smb_ver();
msg.hdr.when_written.time=time(NULL);
msg.hdr.when_written.zone=tzone;
msg.hdr.when_imported=msg.hdr.when_written;
if(smb.status.max_crcs) {
crc=0xffffffffUL;
for(l=0;l<msgtxtlen;l++)
crc=ucrc32(msgtxt[l],crc);
crc=~crc;
i=smb_addcrc(&smb,crc);
if(i) {
fprintf(stderr,"\n\7!smb_addcrc returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1);
}
}
msg.hdr.offset=offset;
if(to==NULL) {
printf("To User Name: ");
fgets(str,sizeof(str)-1,stdin);
} else
sprintf(str,"%.*s",sizeof(str)-1,to);
truncsp(str);
i=smb_hfield(&msg,RECIPIENT,(ushort)strlen(str),str);
if(i) {
fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
if(type=='E' || type=='N')
smb.status.attr|=SMB_EMAIL;
if(smb.status.attr&SMB_EMAIL) {
if(to_number==NULL) {
printf("To User Number (0=QWKnet or Internet): ");
gets(str);
} else
sprintf(str,"%.*s",sizeof(str)-1,to_number);
truncsp(str);
i=smb_hfield(&msg,RECIPIENTEXT,(ushort)strlen(str),str);
if(i) {
fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1);
}
msg.idx.to=atoi(str); }
else {
strlwr(str);
msg.idx.to=crc16(str);
}
if(smb.status.attr&SMB_EMAIL && (type=='N' || !msg.idx.to)) {
if(to_address==NULL) {
printf("To Address: ");
gets(str);
} else
sprintf(str,"%.*s",sizeof(str)-1,to_address);
truncsp(str);
if(*str) {
if(strchr(str,'.'))
net=NET_INTERNET;
else
net=NET_QWK;
i=smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
if(i) {
fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
i=smb_hfield(&msg,RECIPIENTNETADDR,(ushort)strlen(str),str);
if(i) {
fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1);
}
}
}
if(from==NULL) {
printf("From User Name: ");
gets(str);
} else
sprintf(str,"%.*s",sizeof(str)-1,from);
truncsp(str);
i=smb_hfield(&msg,SENDER,(ushort)strlen(str),str);
if(i) {
fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
if(smb.status.attr&SMB_EMAIL) {
if(from_number==NULL) {
printf("From User Number: ");
gets(str);
} else
sprintf(str,"%.*s",sizeof(str)-1,from_number);
truncsp(str);
i=smb_hfield(&msg,SENDEREXT,(ushort)strlen(str),str);
if(i) {
fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1);
}
msg.idx.from=atoi(str);
} else {
strlwr(str);
msg.idx.from=crc16(str);
}
if(subject==NULL) {
printf("Subject: ");
gets(str);
} else
sprintf(str,"%.*s",sizeof(str)-1,subject);
truncsp(str);
i=smb_hfield(&msg,SUBJECT,(ushort)strlen(str),str);
if(i) {
fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1);
}
remove_re(str);
strlwr(str);
msg.idx.subj=crc16(str);
i=smb_dfield(&msg,TEXT_BODY,length);
if(i) {
fprintf(stderr,"\n\7!smb_dfield returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
if(i) {
fprintf(stderr,"\n\7!smb_addmsghdr returned %d: %s\n",i,smb.last_error);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
smb_freemsgmem(&msg);
free(msgtxt);
}
/****************************************************************************/
/* Shows the message base header */
/****************************************************************************/
void showstatus(void)
{
int i;
i=smb_locksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
return; }
i=smb_getstatus(&smb);
smb_unlocksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
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"
"attr =%04Xh\n"
,smb.status.last_msg
,smb.status.total_msgs
,smb.status.header_offset
,smb.status.max_crcs
,smb.status.max_msgs
,smb.status.max_age
,smb.status.attr
);
}
/****************************************************************************/
/* Configure message base header */
/****************************************************************************/
void config(void)
{
char max_msgs[128],max_crcs[128],max_age[128],header_offset[128],attr[128];
int i;
i=smb_locksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
return; }
i=smb_getstatus(&smb);
smb_unlocksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
return; }
printf("Header offset =%-5lu New value (CR=No Change): "
,smb.status.header_offset);
gets(header_offset);
printf("Max msgs =%-5lu New value (CR=No Change): "
,smb.status.max_msgs);
gets(max_msgs);
printf("Max crcs =%-5lu New value (CR=No Change): "
,smb.status.max_crcs);
gets(max_crcs);
printf("Max age =%-5u New value (CR=No Change): "
,smb.status.max_age);
gets(max_age);
printf("Attributes =%-5u New value (CR=No Change): "
,smb.status.attr);
gets(attr);
i=smb_locksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
return; }
i=smb_getstatus(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
smb_unlocksmbhdr(&smb);
return; }
if(isdigit(max_msgs[0]))
smb.status.max_msgs=atol(max_msgs);
if(isdigit(max_crcs[0]))
smb.status.max_crcs=atol(max_crcs);
if(isdigit(max_age[0]))
smb.status.max_age=atoi(max_age);
if(isdigit(header_offset[0]))
smb.status.header_offset=atol(header_offset);
if(isdigit(attr[0]))
smb.status.attr=atoi(attr);
i=smb_putstatus(&smb);
smb_unlocksmbhdr(&smb);
if(i)
fprintf(stderr,"\n\7!smb_putstatus returned %d: %s\n",i,smb.last_error);
}
/****************************************************************************/
/* Lists messages' to, from, and subject */
/****************************************************************************/
void listmsgs(ulong start, ulong count)
{
int i;
ulong l=0;
smbmsg_t msg;
if(!start)
start=1;
fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
while(l<count) {
if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
break;
i=smb_lockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
break; }
i=smb_getmsghdr(&smb,&msg);
smb_unlockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
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[512];
char tmp[128];
int i;
str[0]=0;
for(i=0;i<length;i++)
if(buf[i] && (buf[i]<SP || buf[i]>=0x7f) && buf[i]!=CR && buf[i]!=LF)
break;
if(i==length) /* not binary */
return(buf);
for(i=0;i<length;i++) {
sprintf(tmp,"%02X ",buf[i]);
strcat(str,tmp);
if(i>=100) {
strcat(str,"...");
break;
}
}
return(str);
}
/****************************************************************************/
/* Generates a 24 character ASCII string that represents the time_t pointer */
/* Used as a replacement for ctime() */
/****************************************************************************/
char *timestr(time_t *intime)
{
static char str[256];
char mer[3],hour;
struct tm *gm;
gm=localtime(intime);
if(gm==NULL) {
strcpy(str,"Invalid Time");
return(str); }
if(gm->tm_hour>=12) {
if(gm->tm_hour==12)
hour=12;
else
hour=gm->tm_hour-12;
strcpy(mer,"pm"); }
else {
if(gm->tm_hour==0)
hour=12;
else
hour=gm->tm_hour;
strcpy(mer,"am"); }
sprintf(str,"%s %s %02d %4d %02d:%02d %s"
,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
,hour,gm->tm_min,mer);
return(str);
}
/****************************************************************************/
/* Converts when_t.zone into ASCII format */
/****************************************************************************/
char *zonestr(short zone)
{
static char str[32];
switch((ushort)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:%02u",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;
if(!start)
start=1;
fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
while(l<count) {
if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
break;
i=smb_lockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
break; }
i=smb_getmsghdr(&smb,&msg);
smb_unlockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
break; }
sprintf(when_written,"%.24s %s"
,timestr((time_t*)&msg.hdr.when_written.time)
,zonestr(msg.hdr.when_written.zone));
sprintf(when_imported,"%.24s %s"
,timestr((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 (%ld)\n"
"%-20.20s %ld\n"
"%-20.20s %ld\n"
"%-20.20s %ld\n"
"%-20.20s %s\n"
"%-20.20s %06lXh\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,
ftell(smb.sid_fp)/sizeof(idxrec_t),
"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[%02u].type %02Xh\n"
"dfield[%02u].offset %lu\n"
"dfield[%02u].length %lu\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[%02u].type %02Xh\n"
"hfield[%02u].length %d\n"
"hfield[%02u]_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;
smbmsg_t msg;
idxrec_t HUGE16 *idx;
printf("Maintaining %s\r\n",smb.file);
now=time(NULL);
i=smb_locksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
return; }
i=smb_getstatus(&smb);
if(i) {
smb_unlocksmbhdr(&smb);
fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
return; }
if(!smb.status.total_msgs) {
smb_unlocksmbhdr(&smb);
printf("Empty\n");
return; }
printf("Loading index...\n");
if((idx=(idxrec_t *)LMALLOC(sizeof(idxrec_t)*smb.status.total_msgs))
==NULL) {
smb_unlocksmbhdr(&smb);
fprintf(stderr,"\n\7!Error allocating %lu bytes of memory\n"
,sizeof(idxrec_t)*smb.status.total_msgs);
return; }
fseek(smb.sid_fp,0L,SEEK_SET);
for(l=0;l<smb.status.total_msgs;l++) {
printf("%lu of %lu\r"
,l+1,smb.status.total_msgs);
if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp))
break; }
printf("\nDone.\n\n");
printf("Scanning for pre-flagged messages...\n");
for(m=0;m<l;m++) {
printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
if(idx[m].attr&MSG_DELETE)
flagged++; }
printf("\r100%% (%lu pre-flagged for deletion)\n",flagged);
if(smb.status.max_age) {
printf("Scanning for messages more than %u days old...\n"
,smb.status.max_age);
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((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L)
>smb.status.max_age) {
f++;
flagged++;
idx[m].attr|=MSG_DELETE; } } /* mark for deletion */
printf("\r100%% (%lu flagged for deletion)\n",f); }
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>smb.status.max_msgs) {
printf("Flagging excess messages for deletion...\n");
for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) {
if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
continue;
printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs);
flagged++;
idx[m].attr|=MSG_DELETE; } /* mark for deletion */
printf("\nDone.\n\n"); }
if(!flagged) { /* No messages to delete */
LFREE(idx);
smb_unlocksmbhdr(&smb);
return; }
if(!(mode&NOANALYSIS)) {
printf("Freeing allocated header and data blocks for deleted messages...\n");
if(!(smb.status.attr&SMB_HYPERALLOC)) {
i=smb_open_da(&smb);
if(i) {
smb_unlocksmbhdr(&smb);
fprintf(stderr,"\n\7!smb_open_da returned %d: %s\n",i,smb.last_error);
exit(1); }
i=smb_open_ha(&smb);
if(i) {
smb_unlocksmbhdr(&smb);
fprintf(stderr,"\n\7!smb_open_ha returned %d: %s\n",i,smb.last_error);
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(&smb,&msg))!=0) {
fprintf(stderr,"\n\7!smb_getmsgidx returned %d: %s\n",i,smb.last_error);
continue; }
i=smb_lockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
break; }
if((i=smb_getmsghdr(&smb,&msg))!=0) {
smb_unlockmsghdr(&smb,&msg);
fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
break; }
msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */
if((i=smb_putmsg(&smb,&msg))!=0) {
smb_freemsgmem(&msg);
smb_unlockmsghdr(&smb,&msg);
fprintf(stderr,"\n\7!smb_putmsg returned %d: %s\n",i,smb.last_error);
break; }
smb_unlockmsghdr(&smb,&msg);
if((i=smb_freemsg(&smb,&msg))!=0) {
smb_freemsgmem(&msg);
fprintf(stderr,"\n\7!smb_freemsg returned %d: %s\n",i,smb.last_error);
break; }
smb_freemsgmem(&msg); } }
if(!(smb.status.attr&SMB_HYPERALLOC)) {
smb_close_ha(&smb);
smb_close_da(&smb); }
printf("\nDone.\n\n"); }
printf("Re-writing index...\n");
rewind(smb.sid_fp);
if(chsize(fileno(smb.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,smb.sid_fp); }
printf("\nDone.\n\n");
fflush(smb.sid_fp);
LFREE(idx);
smb.status.total_msgs-=flagged;
smb_putstatus(&smb);
smb_unlocksmbhdr(&smb);
}
typedef struct {
ulong old,new;
} datoffset_t;
/****************************************************************************/
/* Removes all unused blocks from SDT and SHD files */
/****************************************************************************/
void packmsgs(ulong packable)
{
uchar str[128],buf[SDT_BLOCK_LEN],ch,fname[128],tmpfname[128];
int i,size;
ulong l,m,n,datoffsets=0,length,total,now;
FILE *tmp_sdt,*tmp_shd,*tmp_sid;
smbhdr_t hdr;
smbmsg_t msg;
datoffset_t *datoffset=NULL;
now=time(NULL);
printf("Packing %s\n",smb.file);
i=smb_locksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
return; }
i=smb_getstatus(&smb);
if(i) {
smb_unlocksmbhdr(&smb);
fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
return; }
if(!(smb.status.attr&SMB_HYPERALLOC)) {
i=smb_open_ha(&smb);
if(i) {
smb_unlocksmbhdr(&smb);
fprintf(stderr,"\n\7!smb_open_ha returned %d: %s\n",i,smb.last_error);
return; }
i=smb_open_da(&smb);
if(i) {
smb_unlocksmbhdr(&smb);
smb_close_ha(&smb);
fprintf(stderr,"\n\7!smb_open_da returned %d: %s\n",i,smb.last_error);
return; } }
if(!smb.status.total_msgs) {
printf("Empty\n");
rewind(smb.shd_fp);
chsize(fileno(smb.shd_fp),smb.status.header_offset);
rewind(smb.sdt_fp);
chsize(fileno(smb.sdt_fp),0L);
rewind(smb.sid_fp);
chsize(fileno(smb.sid_fp),0L);
if(!(smb.status.attr&SMB_HYPERALLOC)) {
rewind(smb.sha_fp);
chsize(fileno(smb.sha_fp),0L);
rewind(smb.sda_fp);
chsize(fileno(smb.sda_fp),0L);
smb_close_ha(&smb);
smb_close_da(&smb); }
smb_unlocksmbhdr(&smb);
return; }
if(!(smb.status.attr&SMB_HYPERALLOC) && !(mode&NOANALYSIS)) {
printf("Analyzing data blocks...\n");
length=filelength(fileno(smb.sda_fp));
fseek(smb.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,smb.sda_fp))
break;
if(!i)
m++; }
printf("\rAnalyzing header blocks...\n");
length=filelength(fileno(smb.sha_fp));
fseek(smb.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,smb.sha_fp))
break;
if(!ch)
n++; }
if(!m && !n) {
printf("\rAlready compressed.\n\n");
smb_close_ha(&smb);
smb_close_da(&smb);
smb_unlocksmbhdr(&smb);
return; }
if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
printf("\rLess than %luk compressible bytes.\n\n",packable);
smb_close_ha(&smb);
smb_close_da(&smb);
smb_unlocksmbhdr(&smb);
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); }
if(!(smb.status.attr&SMB_HYPERALLOC)) {
rewind(smb.sha_fp);
chsize(fileno(smb.sha_fp),0L); /* Reset both allocation tables */
rewind(smb.sda_fp);
chsize(fileno(smb.sda_fp),0L); }
if(smb.status.attr&SMB_HYPERALLOC && !(mode&NOANALYSIS)) {
printf("Analyzing %s\n",smb.file);
length=filelength(fileno(smb.shd_fp));
m=n=0;
for(l=smb.status.header_offset;l<length;l+=size) {
printf("\r%2u%% ",(long)(100.0/((float)length/l)));
msg.idx.offset=l;
if((i=smb_lockmsghdr(&smb,&msg))!=0) {
printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
size=SHD_BLOCK_LEN;
continue; }
if((i=smb_getmsghdr(&smb,&msg))!=0) {
smb_unlockmsghdr(&smb,&msg);
m++;
size=SHD_BLOCK_LEN;
continue; }
smb_unlockmsghdr(&smb,&msg);
if(msg.hdr.attr&MSG_DELETE) {
m+=smb_hdrblocks(msg.hdr.length);
total=0;
for(i=0;i<msg.hdr.total_dfields;i++)
total+=msg.dfield[i].length;
n+=smb_datblocks(total); }
size=smb_getmsghdrlen(&msg);
if(size<1) size=SHD_BLOCK_LEN;
while(size%SHD_BLOCK_LEN)
size++;
smb_freemsgmem(&msg); }
if(!m && !n) {
printf("\rAlready compressed.\n\n");
smb_unlocksmbhdr(&smb);
return; }
if(packable && (n*SDT_BLOCK_LEN)+(m*SHD_BLOCK_LEN)<packable*1024L) {
printf("\rLess than %luk compressible bytes.\n\n",packable);
smb_unlocksmbhdr(&smb);
return; }
printf("\rCompressing %lu data blocks (%lu bytes)\n"
" and %lu header blocks (%lu bytes)\n"
,n,n*SDT_BLOCK_LEN,m,m*SHD_BLOCK_LEN); }
sprintf(fname,"%s.sd$",smb.file);
tmp_sdt=fopen(fname,"wb");
sprintf(fname,"%s.sh$",smb.file);
tmp_shd=fopen(fname,"wb");
sprintf(fname,"%s.si$",smb.file);
tmp_sid=fopen(fname,"wb");
if(!tmp_sdt || !tmp_shd || !tmp_sid) {
smb_unlocksmbhdr(&smb);
if(!(smb.status.attr&SMB_HYPERALLOC)) {
smb_close_ha(&smb);
smb_close_da(&smb); }
fprintf(stderr,"\n\7!Error opening temp files\n");
return; }
setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
if(!(smb.status.attr&SMB_HYPERALLOC)
&& (datoffset=(datoffset_t *)LMALLOC(sizeof(datoffset_t)*smb.status.total_msgs))
==NULL) {
smb_unlocksmbhdr(&smb);
smb_close_ha(&smb);
smb_close_da(&smb);
fclose(tmp_sdt);
fclose(tmp_shd);
fclose(tmp_sid);
fprintf(stderr,"\n\7!Error allocating memory\n");
return; }
fseek(smb.shd_fp,0L,SEEK_SET);
fread(&hdr,1,sizeof(smbhdr_t),smb.shd_fp);
fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
fwrite(&(smb.status),1,sizeof(smbstatus_t),tmp_shd);
for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<smb.status.header_offset;l++) {
fread(&ch,1,1,smb.shd_fp); /* copy additional base header records */
fwrite(&ch,1,1,tmp_shd); }
fseek(smb.sid_fp,0L,SEEK_SET);
total=0;
for(l=0;l<smb.status.total_msgs;l++) {
printf("%lu of %lu\r",l+1,smb.status.total_msgs);
if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
break;
if(msg.idx.attr&MSG_DELETE) {
printf("\nDeleted index.\n");
continue; }
i=smb_lockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
continue; }
i=smb_getmsghdr(&smb,&msg);
smb_unlockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
continue; }
if(msg.hdr.attr&MSG_DELETE) {
printf("\nDeleted header.\n");
smb_freemsgmem(&msg);
continue; }
if(msg.expiration.time && msg.expiration.time<=now) {
printf("\nExpired message.\n");
smb_freemsgmem(&msg);
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(&smb,datoffset[m].new,smb_getmsgdatlen(&msg),1); }
else {
if(!(smb.status.attr&SMB_HYPERALLOC))
datoffset[datoffsets].old=msg.hdr.offset;
fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);
m=smb_getmsgdatlen(&msg);
if(m>16L*1024L*1024L) {
fprintf(stderr,"\n\7!Invalid data length (%lu)\n",m);
continue; }
if(!(smb.status.attr&SMB_HYPERALLOC)) {
datoffset[datoffsets].new=msg.hdr.offset
=smb_fallocdat(&smb,m,1);
datoffsets++;
fseek(tmp_sdt,msg.hdr.offset,SEEK_SET); }
else {
fseek(tmp_sdt,0L,SEEK_END);
msg.hdr.offset=ftell(tmp_sdt); }
/* Actually copy the data */
n=smb_datblocks(m);
for(m=0;m<n;m++) {
fread(buf,1,SDT_BLOCK_LEN,smb.sdt_fp);
if(!m && *(ushort *)buf!=XLAT_NONE && *(ushort *)buf!=XLAT_LZH) {
printf("\nUnsupported translation type (%04X)\n"
,*(ushort *)buf);
break; }
fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); }
if(m<n)
continue; }
/* Write the new index entry */
length=smb_getmsghdrlen(&msg);
if(smb.status.attr&SMB_HYPERALLOC)
msg.idx.offset=ftell(tmp_shd);
else
msg.idx.offset=smb_fallochdr(&smb,length)+smb.status.header_offset;
msg.idx.number=msg.hdr.number;
msg.idx.attr=msg.hdr.attr;
msg.idx.time=msg.hdr.when_imported.time;
sprintf(str,"%.128s",msg.subj);
strlwr(str);
remove_re(str);
msg.idx.subj=crc16(str);
if(smb.status.attr&SMB_EMAIL) {
if(msg.to_ext)
msg.idx.to=atoi(msg.to_ext);
else
msg.idx.to=0;
if(msg.from_ext)
msg.idx.from=atoi(msg.from_ext);
else
msg.idx.from=0; }
else {
sprintf(str,"%.128s",msg.to);
strlwr(str);
msg.idx.to=crc16(str);
sprintf(str,"%.128s",msg.from);
strlwr(str);
msg.idx.from=crc16(str); }
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); }
if(datoffset)
LFREE(datoffset);
if(!(smb.status.attr&SMB_HYPERALLOC)) {
smb_close_ha(&smb);
smb_close_da(&smb); }
/* Change *.sh$ into *.shd */
fclose(smb.shd_fp);
fclose(tmp_shd);
sprintf(fname,"%s.shd",smb.file);
if(remove(fname)!=0)
fprintf(stderr,"\n\7!Error %d removing %s\n",errno,fname);
sprintf(tmpfname,"%s.sh$",smb.file);
if(rename(tmpfname,fname)!=0)
fprintf(stderr,"\n\7!Error %d renaming %s to %s\n",errno,tmpfname,fname);
/* Change *.sd$ into *.sdt */
fclose(smb.sdt_fp);
fclose(tmp_sdt);
sprintf(fname,"%s.sdt",smb.file);
if(remove(fname)!=0)
fprintf(stderr,"\n\7!Error %d removing %s\n",errno,fname);
sprintf(tmpfname,"%s.sd$",smb.file);
if(rename(tmpfname,fname)!=0)
fprintf(stderr,"\n\7!Error %d renaming %s to %s\n",errno,tmpfname,fname);
/* Change *.si$ into *.sid */
fclose(smb.sid_fp);
fclose(tmp_sid);
sprintf(fname,"%s.sid",smb.file);
if(remove(fname)!=0)
fprintf(stderr,"\n\7!Error %d removing %s\n",errno,fname);
sprintf(tmpfname,"%s.si$",smb.file);
if(rename(tmpfname,fname)!=0)
fprintf(stderr,"\n\7!Error %d renaming %s to %s\n",errno,tmpfname,fname);
if((i=smb_open(&smb))!=0) {
fprintf(stderr,"\n\7!Error %d reopening %s\n",i,smb.file);
return; }
smb.status.total_msgs=total;
if((i=smb_putstatus(&smb))!=0)
fprintf(stderr,"\n\7!smb_putstatus returned %d: %s\n",i,smb.last_error);
printf("\nDone.\n\n");
}
/****************************************************************************/
/* Read messages in message base */
/****************************************************************************/
void readmsgs(ulong start)
{
char HUGE16 *inbuf;
int i,done=0,domsg=1;
smbmsg_t msg;
if(start)
msg.offset=start-1;
else
msg.offset=0;
while(!done) {
if(domsg) {
fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
break;
i=smb_lockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
break; }
i=smb_getmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
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"
,timestr((time_t*)&msg.hdr.when_written.time)
,zonestr(msg.hdr.when_written.zone));
printf("\n\n");
if((inbuf=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS))!=NULL) {
printf("%s",inbuf);
FREE(inbuf); }
i=smb_unlockmsghdr(&smb,&msg);
if(i) {
fprintf(stderr,"\n\7!smb_unlockmsghdr returned %d: %s\n",i,smb.last_error);
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; } }
}
time_t checktime(void)
{
struct tm tm;
memset(&tm,0,sizeof(tm));
tm.tm_year=94;
tm.tm_mday=1;
return(mktime(&tm)-0x2D24BD00L);
}
/***************/
/* Entry point */
/***************/
int main(int argc, char **argv)
{
char cmd[128]="",*p,*s;
char* to=NULL;
char* to_number=NULL;
char* to_address=NULL;
char* from=NULL;
char* from_number=NULL;
char* subj=NULL;
FILE* fp;
int i,j,x,y;
time_t t;
BOOL create=FALSE;
setvbuf(stdout,0,_IONBF,0);
smb.file[0]=0;
fprintf(stderr,"\nSMBUTIL Version %s (%s) SMBLIB %s - Synchronet Message Base "\
"Utility\n\n"
,SMBUTIL_VER
#if defined(__linux__)
,"Linux"
#elif defined(__unix__)
,"Unix"
#elif defined(__OS2__)
,"OS/2"
#elif defined(_WIN32)
,"Win32"
#elif defined(__DOS4G__)
,"DOS4G"
#elif defined(__FLAT__)
,"DOS32"
#else
,"DOS16"
#endif
,smb_lib_ver()
);
putenv("TZ=UCT0");
tzset();
if((t=checktime())!=0) {
fprintf(stderr,"!TIME PROBLEM (%ld)\n",t);
return(-1);
}
for(x=1;x<argc && x>0;x++) {
if(
#ifndef __unix__
argv[x][0]=='/' || /* for backwards compatibilty */
#endif
argv[x][0]=='-') {
for(j=1;argv[x][j];j++)
switch(toupper(argv[x][j])) {
case 'A':
mode|=NOANALYSIS;
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;
case 'C':
create=TRUE;
break;
case 'T':
to=argv[x]+j+1;
j=strlen(argv[x])-1;
break;
case 'U':
to_number=argv[x]+j+1;
j=strlen(argv[x])-1;
break;
case 'N':
to_address=argv[x]+j+1;
j=strlen(argv[x])-1;
break;
case 'F':
from=argv[x]+j+1;
j=strlen(argv[x])-1;
break;
case 'E':
from_number=argv[x]+j+1;
j=strlen(argv[x])-1;
break;
case 'S':
subj=argv[x]+j+1;
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(s==NULL)
s=strrchr(smb.file,'\\');
if(p>s) *p=0;
smb.retry_time=30;
fprintf(stderr,"Opening %s\r\n",smb.file);
if((i=smb_open(&smb))!=0) {
fprintf(stderr,"\n\7!Error %d (%s) opening %s message base\n"
,i,smb.last_error,smb.file);
exit(1); }
if(!filelength(fileno(smb.shd_fp))) {
if(!create) {
printf("Empty\n");
smb_close(&smb);
continue; }
smb.status.max_crcs=0;
smb.status.max_age=0;
smb.status.max_msgs=1000;
smb.status.attr=0;
if((i=smb_create(&smb))!=0) {
smb_close(&smb);
printf("!Error %d (%s) creating %s\n",i,smb.last_error,smb.file);
continue;
}
}
for(y=0;cmd[y];y++)
switch(toupper(cmd[y])) {
case 'I':
case 'E':
case 'N':
if(cmd[1]!=0) {
if((fp=fopen(cmd+1,"r"))==NULL) {
fprintf(stderr,"\n\7!Error %d opening %s\n"
,errno,cmd+1);
exit(1);
}
} else
fp=stdin;
i=smb_locksmbhdr(&smb);
if(i) {
fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
return(1); }
postmsg((char)toupper(cmd[y]),to,to_number,to_address,from,from_number,subj,fp);
fclose(fp);
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(&smb); } } }
if(!cmd[0])
printf("%s",usage);
return(0);
}