home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
XGRP_000.SZH
/
EMAILOUT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-23
|
15KB
|
517 lines
/* echomail scanner */
#include <limits.h>
#include "xgroup.h"
#define MAXKLUDGE 256
#define SETSCANNED(x) (x.m_attr |= MSGSCANNED)
#define SETSENT(x) (x.attr |= MSGSENT)
#define RESETSENT(x) (x.attr &= (~MSGSENT))
#define SETDELETED(x) (x.m_attr |= MSGDELETED)
/* function declarations specific to this module */
static int _fastcall open_pkt (ADDR *addr);
static word _fastcall find_last_scanned (int dataptr);
static int _fastcall write_pkt_msg (int fp,XMSG *amsg,char *npth,
char *text,char *area);
static void _fastcall report(void);
static void _fastcall do_export(ECHOREC *einfo,word startat,int dataptr,
int textptr);
/* external var references */
extern GROUP *group;
extern CONTROLS control;
extern ADDR *myaddr;
extern ECHOREC *echos;
extern char *groupin;
extern char *groupout;
extern char *grouphold;
extern char *msgdir;
extern char *archive;
extern char *unarchive;
extern char *outbound;
extern char *inbound;
extern word packsize;
extern char buffer[1024];
extern word netarea;
extern DUPES *dupes;
extern word nextdupe,maxdupes;
extern char founddupes;
void _fastcall echo_export_mail (void) {
word y;
ECHOREC *currecho;
int dataptr,textptr;
struct stat st;
currecho = echos;
while(currecho) {
if(!currecho->addr || !currecho->areano) { /* pass-thru or local-only */
currecho = currecho->next;
continue;
}
printf("\nScanning echo area \"%s\"...",currecho->tag);
sprintf(buffer,"%s/XDATA.%03x",msgdir,currecho->areano);
if(stat(buffer,&st)) st.st_size = 0L;
if(!st.st_size) {
printf("no msgs\n\x1b[K");
currecho = currecho->next;
continue;
}
else printf("%u msg%s\n\x1b[K",
(word)(st.st_size / (long)sizeof(XMSG)),
&"s"[((word)(st.st_size / (long)sizeof(XMSG)) == 1)]);
dataptr = sopen(buffer,O_RDWR | O_BINARY,SH_DENYNO);
if(dataptr == -1) {
printf("\nCouldn't open data file %s\n",buffer);
currecho = currecho->next;
continue;
}
sprintf(buffer,"%s/XTEXT.%03x",msgdir,currecho->areano);
textptr = sopen(buffer,O_RDWR | O_BINARY,SH_DENYNO);
if(textptr == -1) {
close(dataptr);
printf("\nCouldn't open text file %s\n",buffer);
currecho = currecho->next;
continue;
}
y = find_last_scanned(dataptr);
do_export(currecho,y,dataptr,textptr);
close(textptr);
close(dataptr);
currecho = currecho->next;
}
report();
}
void _fastcall report (void) {
ECHOREC *einfo = echos;
long totalmsgs = 0L;
printf("\n");
while(einfo) {
if(einfo->exported) {
logf("Exported %u msg%s from area #%u \"%s\"",einfo->exported,
&"s"[(einfo->exported == 1)],einfo->areano,einfo->tag);
totalmsgs += (long)einfo->exported;
}
einfo = einfo->next;
}
if(totalmsgs) logf("Total msgs exported: %lu",totalmsgs);
}
static void _fastcall do_export (ECHOREC *einfo,word startat,int dataptr,
int textptr) {
word x,tries,test;
word nummsgs;
long pos,msgidcrc,serialno;
int fp;
char *text = NULL,npthbuf[90],*p,*pp;
XMSG xmsg;
ADDR *addr,*maddr;
SB *s;
if(!control.nodupes) load_dupes(einfo->areano);
tries = 0;
while(tries < 50) {
if(lseek(dataptr,0L,SEEK_END) != -1L) break;
DosSleep(100L);
tries++;
}
if(tries >= 50) {
printf("\nLocking conflict; aborting...(#4)\n");
my_free(dupes);
return;
}
nummsgs = (word)(tell(dataptr) / (long)sizeof(XMSG));
if(startat) startat--;
for(x = startat;x < nummsgs;x++) {
tries = 0;
while(tries < 50) {
if(lseek(dataptr,(long)x * (long)sizeof(XMSG),SEEK_SET) != -1L) break;
DosSleep(100L);
tries++;
}
if(tries >= 50) {
printf("\nLocking conflict; aborting...(#5)\n");
my_free(dupes);
return;
}
pos = tell(dataptr);
tries = 0;
while(tries < 50) {
if((size_t)read(dataptr,&xmsg,sizeof(XMSG)) == sizeof(XMSG)) break;
DosSleep(100L);
tries++;
lseek(dataptr,pos,SEEK_SET);
}
if(tries >= 50) {
printf("\nLocking conflict; aborting...(#6)\n");
return;
}
if(xmsg.m_attr & MSGSCANNED) continue;
if(xmsg.m_attr & MSGDELETED) goto ExportDone;
if(!(xmsg.m_attr & MSGECHO)) goto ExportDone;
if(!(xmsg.attr & MSGLOCAL)) goto ExportDone;
if(xmsg.attr & MSGORPHAN) goto ExportDone;
/* Got one to export */
RESETSENT(xmsg); /* Reset sent bit--what the hell, be nice */
tries = 0;
while(tries < 50) {
if(lseek(textptr,xmsg.start,SEEK_SET) != -1L) break;
DosSleep(100L);
tries++;
}
if(tries >= 50) {
printf("\nLocking conflict; aborting...(#7)\n");
my_free(dupes);
return;
}
text = (char *)malloc(xmsg.length + 2);
if(!text) continue;
tries = 0;
while(tries < 50) {
*text = 0;
test = (word)read(textptr,text,xmsg.length + 1);
if(test != 65535U) {
if(test >= (xmsg.length - 1)) break;
}
DosSleep(100L);
tries++;
lseek(textptr,xmsg.start,SEEK_SET);
}
if(tries >= 50) {
printf("\nLocking conflict; aborting...(#9)\n");
return;
}
if(!*text){
my_free(text);
text = NULL;
continue;
}
if(xmsg.m_attr & MSGPACKED) {
if(unpack_msg(&text) == NULL) {
my_free(text);
text = NULL;
continue;
}
}
addr = einfo->addr;
if(addr) {
einfo->exported++;
maddr = best_guess(addr,myaddr);
/* construct new path entry */
if(maddr->point) {
sprintf(npthbuf,"\01NPTH: %s#%u:%u/%u.%u\r",maddr->domain,
maddr->zone,maddr->net,maddr->node,maddr->point);
}
else {
sprintf(npthbuf,"\01NPTH: %s#%u:%u/%u\r",maddr->domain,
maddr->zone,maddr->net,maddr->node);
}
}
while(addr) {
fp = open_pkt(addr);
if(fp == -1) {
addr = addr->next;
if(addr) continue;
my_free(text);
text = NULL;
break;
}
xmsg.d_zone = addr->zone;
xmsg.dest_net = addr->net;
xmsg.dest = addr->node;
xmsg.d_point = addr->point;
printf("#%u (#%u)\r",
x+1,einfo->exported);
text[xmsg.length] = 0;
text[xmsg.length-1] = 0;
write_pkt_msg(fp,&xmsg,npthbuf,text,einfo->tag);
/* add tiny seen-bys */
s = make_tinysbs(einfo,NULL);
if(s) {
lseek(fp,(tell(fp) - 1L),SEEK_SET);
spit_seenbys(s,fp);
write(fp,"\0\0",3);
lseek(fp,(tell(fp) - 2L),SEEK_SET); /* Ready for another msg */
my_free(s);
}
close(fp);
addr = addr->next;
}
if(!control.nodupes && dupes) {
if(!strcmp(text,"\01MSGID: ")) {
strncpy(npthbuf,&text[8],89);
npthbuf[89] = 0;
p = strchr(npthbuf,'\r');
if(p) *p = 0;
lstrip(npthbuf);
rstrip(npthbuf);
p = strchr(npthbuf,' ');
if(p) {
*p = 0;
msgidcrc = crc32str(npthbuf,1);
*p = ' ';
p++;
pp = p;
serialno = strtol(p,&pp,16);
if((serialno == LONG_MIN || serialno == LONG_MAX) &&
errno == ERANGE) serialno = 0L;
if(msgidcrc && serialno) {
dupes[nextdupe].msgidcrc = msgidcrc;
dupes[nextdupe].serialno = serialno;
nextdupe++;
founddupes = 1;
if(nextdupe >= maxdupes) nextdupe = 0;
}
}
}
}
my_free(text);
text = NULL;
SETSENT(xmsg); /* Set sent bit */
if(xmsg.attr & MSGKILL)
SETDELETED(xmsg); /* delete if so marked*/
ExportDone:
SETSCANNED(xmsg); /* Rewrite header w/ echos-scanned bit set */
tries = 0;
while(tries < 50) {
if(lseek(dataptr,pos,SEEK_SET) != -1L) break;
DosSleep(100L);
tries++;
}
if(tries < 50) {
locking(dataptr,LK_LOCK,(long)sizeof(XMSG));
write(dataptr,&xmsg,sizeof(XMSG));
lseek(dataptr,pos,SEEK_SET);
locking(dataptr,LK_UNLCK,(long)sizeof(XMSG));
}
}
if(dupes) free_dupes();
}
static int _fastcall open_pkt (ADDR *addr) {
int fp;
long pos;
PKTHDR ph;
ADDR *maddr;
static char currout[1027];
char *p;
/* Open (create if necessary) a packet for address given.
Return a file handle for the packet positioned to eop */
if(!control.xbbsos2) {
strcpy(currout,outbound);
if(addr->domain && *addr->domain && stricmp(myaddr->domain,addr->domain)) {
p = strrchr(currout,'\\');
if(p) p++;
else p = &currout[strlen(currout)];
strcat(currout,addr->domain);
}
if(myaddr->zone != addr->zone) {
sprintf(&currout[strlen(currout)],".%03x",addr->zone);
DosMkDir(currout,0L);
}
sprintf(buffer,"%s/%04x%04x.OUT",currout,addr->net,addr->node);
}
else {
sprintf(buffer,"%s/P.%u.%u.%u.%u.%0.8s",outbound,addr->zone,addr->net,
addr->node,addr->point,addr->domain);
}
fp = sopen(buffer,O_RDWR | O_BINARY | O_CREAT,SH_DENYWR,S_IREAD | S_IWRITE);
if(fp != -1) {
lseek(fp,0L,SEEK_END);
if(!tell(fp)) {
memset(&ph,0,sizeof(PKTHDR));
ph.version = 2;
ph.subver = 2;
ph.dnode = addr->node;
ph.dnet = addr->net;
ph.dzone = addr->zone;
ph.dpoint = addr->point;
strncpy(ph.ddomain,addr->domain,8);
maddr = best_guess(addr,myaddr);
ph.onode = maddr->node;
ph.onet = maddr->net;
ph.ozone = maddr->zone;
ph.opoint = maddr->point;
strncpy(ph.odomain,maddr->domain,8);
write(fp,&ph,sizeof(PKTHDR));
write(fp,"\0",2);
}
pos = tell(fp);
if(pos) lseek(fp,pos - 2L,SEEK_SET); /* Position to next msg spot */
}
return fp;
}
static int _fastcall write_pkt_msg (int fp,XMSG *amsg,char *npth,
char *text,char *area) {
char pmsg[192],*p;
word x;
/* Write the message given to the end of the file given as a
packed msg */
memset(pmsg,192,0);
*pmsg = 0x02;
pmsg[1] = 0x00;
memcpy(&pmsg[2],&amsg->orig,2);
memcpy(&pmsg[4],&amsg->dest,2);
memcpy(&pmsg[6],&amsg->orig_net,2);
memcpy(&pmsg[8],&amsg->dest_net,2);
memcpy(&pmsg[10],&amsg->attr,2);
x = 0;
memcpy(&pmsg[12],&x,2);
for(x = 0;x < 20;x++) if(!amsg->date[x]) amsg->date[x] = 'Q';
amsg->date[19] = 0; /* damn qmail anyway... */
memcpy(&pmsg[14],amsg->date,20);
p = &pmsg[34];
strcpy(p,amsg->to);
x = 34;
while(*p){
x++;
p++;
}
p++;
x++;
strcpy(p,amsg->from);
while(*p){
x++;
p++;
}
x++;
p++;
strcpy(p,amsg->subj);
while(*p){
x++;
p++;
}
x++;
p++;
write(fp,pmsg,x);
if(area && *area) { /* Prepend area tag */
write(fp,"AREA: ",6);
write(fp,area,strlen(area));
write(fp,"\r",1);
}
write(fp,npth,strlen(npth));
write(fp,text,strlen(text));
write(fp,"\0\0",3);
lseek(fp,(tell(fp) - 2L),SEEK_SET); /* Ready for another msg */
return 1;
}
static word _fastcall find_last_scanned (int dataptr) { /* Speed up someday... */
long pos;
register word x;
int tries;
XMSG xmsg;
tries = 0;
while(tries < 50) {
if(lseek(dataptr,0L,SEEK_END) != -1L) break;
DosSleep(100L);
tries++;
}
if(tries >= 50) {
printf("\nLocking conflict; aborting...(#1)\n");
return 0;
}
pos = tell(dataptr);
x = (word)((pos / (long)sizeof(XMSG)) - 1L);
for(;x;x--) {
tries = 0;
while(tries < 50) {
if(lseek(dataptr,(long)x * (long)sizeof(XMSG),SEEK_SET) != -1L) break;
DosSleep(100L);
tries++;
}
if(tries >= 50) {
printf("Locking contention...(#2)\n");
continue;
}
tries = 0;
while(tries < 50) {
if((size_t)read(dataptr,&xmsg,sizeof(XMSG)) == sizeof(XMSG)) break;
DosSleep(100L);
tries++;
lseek(dataptr,(long)x * (long)sizeof(XMSG),SEEK_SET);
}
if(tries >= 50) {
printf("Locking contention...(#3)\n");
continue;
}
if(xmsg.m_attr & MSGSCANNED) break;
}
return x;
}