Category : C Source Code
Archive   : QWKREP.ZIP
Filename : MAIL.C

 
Output of file : MAIL.C contained in archive : QWKREP.ZIP

/*
* mail.c - parse a UUCP mail / news input data stream into messages
*/

#include
#include
#include
#include
#include "callback.h"

extern char *mnam[];

static struct _ng_
{
char *_name;
char *_conf;
} ngs[] =
{
{ "comp.os.cpm", "CPM" },
{ "rec.humor.funny", "FUNNY" },
{ "comp.protocols.kermit", "KERMIT" },
};

/*
* number of newsgroups
*/
#define NUMNG (sizeof(ngs) / sizeof(ngs[0]))

/*
* copy a token from bp to targ, padding to 25 characters with spaces
*/
static tokecpy(targ, bp)
char *targ;
char *bp;
{
int i;

for (i = 0; i < 25 && *bp && *bp != ' ' && *bp != '\t'; i++)
*targ++ = *bp++;
*targ = 0;
}

/*
* parse either form of RFC 822 date
*/
static parsedate(bp)
char *bp;
{
int r;
int i;
int j;
int k;
int hh, mm, ss;
int dd, mo, yy;
struct tm *tmp;
time_t now;
char mtmp[6];
char *bits[10];
char hold[80];

r = 0;
/*
* get the current time
*/
time(&now);
tmp = localtime(&now);

/*
* install that in case we don't get anything useful
*/
sprintf(m_date, "%02d-%02d-%02d", tmp->tm_mon + 1, tmp->tm_mday,
tmp->tm_year % 100);
sprintf(m_time, "%02d:%02d", tmp->tm_hour, tmp->tm_min);

/*
* local copy of what we're parsing
*/
strncpy(hold, bp, 78);
(bp = hold)[78] = 0;

/*
* chop it up into bits, dividing at the spaces
*/
for (i = 0; *bp && i < 10; i++)
{
bits[i] = bp;
if (*(bp = unbyp(bp)))
{
*bp++ = 0;
bp = byp(bp);
}
}

/*
* no date, month or year yet
*/
dd = mo = yy = -1;
for (j = 0; j < i; j++)
{
/*
* nn:nn:nn is a time - process that
*/
if (sscanf((bp = bits[j]), "%d:%d:%d", &hh, &mm, &ss) == 3)

{
sprintf(m_time, "%02d:%02d", hh, mm);
/*
* set time bit in result
*/
r |= 1;
}
/*
* anything numeric is date or year
*/
else if (*bp >= '0' && *bp <= '9')
{
if (dd == -1)
dd = atoi(bp);
else
yy = atoi(bp) % 100;
}
/*
* else see if we can find a month in it
*/
else
{
strncpy(mtmp, bp, 3);
mtmp[3] = 0;
lower(mtmp);
for (k = 0; k < 12; k++)
if (strcmp(mtmp, mnam[k]) == 0)
break;
if (k < 12)
mo = k + 1;
}
}
/*
* got year and month: we must have a full date
*/
if (yy != -1 && mo != -1)
{
sprintf(m_date, "%02d-%02d-%02d", mo, dd, yy);
/*
* set the bit in the result
*/
r |= 2;
}
return(r);
}

/*
* see if the current line is a valid From_ line - i.e. the start of a new
* message in mailbox format
*/
static validfrom(work)
char *work;
{
int i;
char x_date[10];
char x_time[8];

strcpy(x_date, m_date);
strcpy(x_time, m_time);
/*
* look for From_ and a date *AFTER* the address (that's what all the
* byp's and unbyp's do
*/
i = strncmp(work, "From ", 5) == 0 &&
parsedate(byp(unbyp(byp(unbyp(work))))) == 3;
/*
* save the date and time
*/
strcpy(m_date, x_date);
strcpy(m_time, x_time);
return(i);
}

/*
* pull the from name out of what we're given:
* (Name) address --> Name
*
Name --> Name
*
"Name" --> Name
* ...!...!userid --> userid
* [email protected] --> userid
* userid%.... --> userid
*/
static void getfrom(pbp)
char *pbp;
{
char bp[240];
char *p1;
char *p2;

strcpy(bp, pbp);
/*
* look for (..)
*/
if ((p1 = strchr(bp, '(')) != (char *) NULL &&
(p2 = strchr(bp, ')')) != (char *) NULL &&
p1 < p2)
{
*p2 = 0;
/*
* pull it out
*/
strncpy(from, ++p1, 25);
from[25] = 0;
return;
}
/*
* <...> name and <...> "name" forms
*/
if ((p1 = strchr(bp, '<')) != (char *) NULL &&
(p2 = strchr(bp, '>')) != (char *) NULL &&
p1 < p2)
{
/*
* replace everything between < and > (inclusive) with spaces
*/
do
*p1++ = ' ';
while (p1 < p2);
/*
* remove any quotes we might find
*/
for (p1 = bp; *p1; p1++)
if (*p1 == '"')
*p1 = ' ';
/*
* and use whatever is left
*/
p1 = byp(bp);
strncpy(from, p1, 25);
from[25] = 0;
return;
}
/*
* [email protected] and userid%.... forms
*/
if ((p1 = strchr(bp, '%')) != (char *) NULL ||
(p1 = strchr(bp, '@')) != (char *) NULL)
{
/*
* terminate at the @ or %
*/
*p1 = 0;
p1 = byp(bp);
strncpy(from, p1, 25);
from[25] = 0;
return;
}
/*
* ....!userid form
*/
if ((p1 = strrchr(bp, '!')) != (char *) NULL)
{
/*
* copy from the last ! onwards
*/
strncpy(from, ++p1, 25);
from[25] = 0;
return;
}
/*
* else just use what we were given
*/
p1 = byp(bp);
strncpy(from, p1, 25);
from[25] = 0;
return;
}

/*
* convert a newsgroup to it's "ECHO" name
*/
static char *ngcvt(bp)
char *bp;
{
int i;

for (i = 0; i < NUMNG; i++)
if (strstr(bp, ngs[i]._name) != (char *) NULL)
return(ngs[i]._conf);
return("JUNK");
}

/*
* main entry point
*/
int mail_split(line, whoami)
char *line;
{
int i;
char *bp;
static int seen = 0;
static int state = 0;
char work[240];
char text[80];

/*
* grab a local copy
*/
strncpy(work, line, 238);
work[238] = 0;
strip(work);
/*
* skip over the first token
*/
bp = byp(unbyp(work));
/*
* valid from line?
*/
if (validfrom(work))
{
/*
* yes - this must be for us!
*/
if (seen)
/*
* finish a message if we are already in one
*/
finish_msg();
else
{
/*
* first time - set up
* firstly "claim" this packet
*/
mine(whoami);
/*
* init things - note that my name is hard coded
*/
strcpy(bbsname, "UUCP");
strcpy(bbstitle, "UUCP E-mail and news");
strcpy(bbsuser, "DAVID GOODENOUGH");
/*
* force a mail conference
*/
addconf("MAIL");
/*
* flag we're off and going
*/
seen = 1;
}
/*
* start a new message
*/
newmsg();
/*
* grab the from address
*/
tokecpy(from, bp);
/*
* and the date
*/
parsedate(byp(unbyp(bp)));
/*
* fill in the other fields
*/
strcpy(to, bbsuser);
strcpy(confname, "MAIL");
strcpy(subject, "X");
/*
* set state to 1: we're crunching headers
*/
state = 1;
}
else if (strlen(work) == 0)
/*
* empty line finishes headers
*/
state = 0;
if (state)
{
/*
* in headers
*/
if (strncmp(work, "Subject: ", 9) == 0)
{
/*
* grab a subject
*/
strncpy(subject, bp, 25);
subject[25] = 0;
}
else if (strncmp(work, "From: ", 6) == 0)
/*
* grab the from name
*/
getfrom(bp);
else if (strncmp(work, "Date: ", 6) == 0)
/*
* get the date
*/
parsedate(bp);
else if (strncmp(work, "Newsgroups: ", 12) == 0)
{
/*
* newsgroup - no To: user, and convert the newsgroup name
*/
strcpy(to, "ALL");
strcpy(confname, ngcvt(bp));
}
}
if (seen)
{
/*
* if we're running send back the message 78 chars at a time
*/
for (i = 0; strlen(&work[i]) > 78; i += 78)
{
strncpy(text, &work[i], 78);
text[78] = 0;
writemsg(text);
}
writemsg(&work[i]);
}
}