home *** CD-ROM | disk | FTP | other *** search
- /*
- * mail.c - parse a UUCP mail / news input data stream into messages
- */
-
- #include <stdio.h>
- #include <clib.h>
- #include <time.h>
- #include <string.h>
- #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
- * <address> Name --> Name
- * <address> "Name" --> Name
- * ...!...!userid --> userid
- * userid@.... --> 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;
- }
- /*
- * userid@.... 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]);
- }
- }
-