This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbfido/tosspkt.c
2002-01-07 19:16:03 +00:00

615 lines
14 KiB
C

/*****************************************************************************
*
* $Id$
* Purpose ...............: Toss a single *.pkt file
*
*****************************************************************************
* Copyright (C) 1997-2002
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS 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, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************/
#include "../lib/libs.h"
#include "../lib/structs.h"
#include "../lib/users.h"
#include "../lib/records.h"
#include "../lib/common.h"
#include "../lib/clcomm.h"
#include "../lib/msg.h"
#include "../lib/msgtext.h"
#include "../lib/dbcfg.h"
#include "../lib/dbnode.h"
#include "../lib/dbmsgs.h"
#include "../lib/dbdupe.h"
#include "../lib/dbuser.h"
#include "../lib/dbftn.h"
#include "tosspkt.h"
#include "postnetmail.h"
#include "postecho.h"
#include "rollover.h"
/*
* External declarations
*/
extern int do_quiet;
extern int do_unsec;
extern int check_dupe;
extern int autocrea;
extern time_t t_start;
extern int most_debug;
/*
* Global variables
*/
int net_in = 0; /* Netmails received */
int net_imp = 0; /* Netmails imported */
int net_out = 0; /* Netmails forwarded */
int net_bad = 0; /* Bad netmails (tracking errors */
int echo_in = 0; /* Echomail received */
int echo_imp = 0; /* Echomail imported */
int echo_out = 0; /* Echomail forwarded */
int echo_bad = 0; /* Bad echomail */
int echo_dupe = 0; /* Dupe echomail */
int news_in = 0; /* News received */
int news_imp = 0; /* News imported */
int news_out = 0; /* News posted */
int news_bad = 0; /* Bad news */
int news_dupe = 0; /* Dupe articles */
int email_in = 0; /* Email received */
int email_imp = 0; /* Email imported */
int email_out = 0; /* Email forwarded */
int email_bad = 0; /* Bad email */
static int at_zero = 0;
/*
* Internal prototypes
*/
char *aread(char *, int, FILE *);
int importmsg(faddr *, faddr *, faddr *, char *, char *, time_t, int, int, FILE *);
void autocreate(char *, faddr *);
char *aread(char *s, int count, FILE *fp)
{
int i,c,next;
if (feof(fp))
return(NULL);
if (s == NULL)
return NULL;
if (at_zero)
{
at_zero=0;
return NULL;
}
for (i = 0,next = 1; (i < count-1) && next;)
switch (c=getc(fp)) {
case '\n': break;
case '\r': s[i]='\n';
i++;
next=0;
break;
case 0x8d: s[i]=' ';
i++;
break;
case '\0': at_zero=1;
next=0;
break;
default: s[i]=c;
i++;
break;
}
s[i]='\0';
return s;
}
/*
* Import 1 message, forward if needed.
* pkt_from, from, to, subj, orig, mdate, flags, cost, file
*
* 0 - All Seems Well.
* 1 - Can't access messagebase.
* 2 - Cannot open mareas.data
* 3 - Echomail without Origin line.
* 4 - Echomail from unknown node, disconnected node.
* 5 - Locking error.
*
*/
int importmsg(faddr *p_from, faddr *f, faddr *t, char *orig, char *subj,
time_t mdate, int flags, int cost, FILE *fp)
{
char *buf, *marea = NULL;
int echomail = FALSE, rc = 0, bad = FALSE, Known = FALSE, FirstLine;
sysconnect Link;
if (CFG.slow_util && do_quiet)
usleep(1);
memset(&Link, 0, sizeof(Link));
/*
* Increase uplink's statistic counter.
*/
Link.aka.zone = p_from->zone;
Link.aka.net = p_from->net;
Link.aka.node = p_from->node;
Link.aka.point = p_from->point;
if (SearchNode(Link.aka)) {
StatAdd(&nodes.MailRcvd, 1);
UpdateNode();
SearchNode(Link.aka);
Known = TRUE;
}
buf = calloc(2048, sizeof(char));
marea = NULL;
/*
* First read the message for kludges we need.
*/
rewind(fp);
FirstLine = TRUE;
while ((fgets(buf, 2048, fp)) != NULL) {
Striplf(buf);
/*
* Check if message is echomail and if the areas exists.
*/
if (FirstLine && (!strncmp(buf, "AREA:", 5))) {
marea = xstrcpy(tu(buf + 5));
if (orig == NULL) {
Syslog('!', "Echomail without Origin line");
echo_bad++;
echo_in++;
bad = TRUE;
free(buf);
free(marea);
return 3;
}
if (!SearchMsgs(marea)) {
WriteError("Unknown echo area %s", marea);
if (autocrea) {
autocreate(marea, p_from);
if (!SearchMsgs(marea)) {
WriteError("Autocreate of area %s failed.", area);
echo_bad++;
echo_in++;
bad = TRUE;
free(marea);
free(buf);
return 4;
}
} else {
echo_bad++;
echo_in++;
bad = TRUE;
free(buf);
free(marea);
return 4;
}
}
echomail = TRUE;
free(marea);
}
if (*buf != '\001')
FirstLine = FALSE;
} /* end of checking kludges */
if (echomail)
rc = postecho(p_from, f, t, orig, subj, mdate, flags, cost, fp, TRUE);
else
rc = postnetmail(fp, f, t, orig, subj, mdate, flags, TRUE);
free(buf);
return rc;
}
/*
* Create echomail area if it doesn't excist and allowed.
* Contributed by Redy Rodriguez.
*/
void autocreate(char *marea, faddr *p_from)
{
FILE *pMsgs;
char temp[250];
int i;
struct _sysconnect syscon;
if (!SearchMsgs((char *)"DEFAULT")){
WriteError("Can't find DEFAULT area, can't autocreate:");
autocrea = FALSE;
return;
}
sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
if ((pMsgs = fopen(temp, "r+")) == NULL) {
WriteError("$Database error: Can't create %s", temp);
return;
}
strncat(msgs.Name,marea,40-strlen(msgs.Name));
strncpy(msgs.Tag,marea,50);
strncpy(msgs.QWKname,marea,20);
strncat(msgs.Base,marea,64-strlen(msgs.Base));
fseek(pMsgs, 0, SEEK_END);
Syslog('+', "Autocreate area %s", marea);
memset(&syscon, 0, sizeof(syscon));
syscon.aka.zone = p_from->zone;
syscon.aka.node = p_from->node;
syscon.aka.net = p_from->net;
if (SearchFidonet(p_from->zone))
strcpy(syscon.aka.domain,fidonet.domain);
else {
WriteError("New area %s from node of unknown zone %d not created.", marea,p_from->zone);
fclose(pMsgs);
return;
}
syscon.sendto = TRUE;
syscon.receivefrom = TRUE;
if (msgs.Aka.zone == 0) {
for (i = 0; i < 40; i++) {
if (CFG.akavalid[i]) {
msgs.Aka.zone=CFG.aka[i].zone;
msgs.Aka.net=CFG.aka[i].net;
msgs.Aka.node=CFG.aka[i].node;
msgs.Aka.point=CFG.aka[i].point;
strcpy(msgs.Aka.domain,CFG.aka[i].domain);
i=40;
}
}
for (i = 0; i < 40; i++) {
if (CFG.akavalid[i] && (strcmp(CFG.aka[i].domain,msgs.Aka.domain)==0)) {
msgs.Aka.zone=CFG.aka[i].zone;
msgs.Aka.net=CFG.aka[i].net;
msgs.Aka.node=CFG.aka[i].node;
msgs.Aka.point=CFG.aka[i].point;
strcpy(msgs.Aka.domain,CFG.aka[i].domain);
i=40;
}
}
for (i = 0; i < 40; i++) {
if ((CFG.akavalid[i]) && (CFG.aka[i].zone == p_from->zone)) {
msgs.Aka.zone=CFG.aka[i].zone;
msgs.Aka.net=CFG.aka[i].net;
msgs.Aka.node=CFG.aka[i].node;
msgs.Aka.point=CFG.aka[i].point;
strcpy(msgs.Aka.domain,CFG.aka[i].domain);
i=40;
}
}
for (i = 0; i < 40; i++) {
if ((CFG.akavalid[i]) && (CFG.aka[i].zone == p_from->zone) && (CFG.aka[i].net == p_from->net)) {
msgs.Aka.zone=CFG.aka[i].zone;
msgs.Aka.net=CFG.aka[i].net;
msgs.Aka.node=CFG.aka[i].node;
msgs.Aka.point=CFG.aka[i].point;
strcpy(msgs.Aka.domain,CFG.aka[i].domain);
i=40;
}
}
for (i = 0; i < 40; i++) {
if ((CFG.akavalid[i]) && (CFG.aka[i].zone == p_from->zone) &&
(CFG.aka[i].net == p_from->net) && (CFG.aka[i].node == p_from->node)) {
msgs.Aka.zone=CFG.aka[i].zone;
msgs.Aka.net=CFG.aka[i].net;
msgs.Aka.node=CFG.aka[i].node;
msgs.Aka.point=CFG.aka[i].point;
strcpy(msgs.Aka.domain,CFG.aka[i].domain);
i=40;
}
}
}
fwrite(&msgs, msgshdr.recsize, 1, pMsgs);
fwrite(&syscon, sizeof(syscon), 1, pMsgs);
memset(&syscon, 0, sizeof(syscon));
for (i = 1 ; i < CFG.toss_systems; i++ )
fwrite(&syscon, sizeof(syscon), 1, pMsgs);
fclose(pMsgs);
return;
}
/*
* Toss one packet.
*
* 0 -
* 1 - Cannot open packet
* 2 - Bad packet header
* 3 - Packet is not for us
* 4 - Bad password
*/
int TossPkt(char *fn)
{
int rc, count = 0;
static int maxrc = 0;
static faddr from, to;
FILE *pkt;
if (!do_quiet) {
colour(10, 0);
printf("Tossing packet %s\n", fn);
}
if ((pkt = fopen(fn, "r")) == 0) {
WriteError("$Cannot open %s", fn);
return 1;
}
memset(&from, 0, sizeof(faddr));
memset(&to, 0, sizeof(faddr));
if (((rc = getheader(&from, &to, pkt, fn)) != 0)) {
WriteError("%s, aborting",
(rc == 1)?"wrong header type":
(rc == 2)?"bad packet header":
(rc == 3)?"packet is not for us":
(rc == 4)?"bad password":
"bad packet");
return(rc);
}
while ((rc = getmessage(pkt, &from, &to)) == 1) {
count++;
}
Syslog('+', "Messages : %d", count);
maxrc = rc;
if (!do_quiet)
printf("\r \r");
if (rc)
Syslog('+', "End, rc=%d", maxrc);
fclose(pkt);
return maxrc;
}
/*
* Process one message from message packet.
*
* 0 - no more messages
* 1 - more messages
* 2 - bad file
* 3 - bad message header
* 4 - unable to open temp file
* 5 - unexpected end of packet
* >10 - import error
*/
int getmessage(FILE *pkt, faddr *p_from, faddr *p_to)
{
char buf[2048];
char *orig = NULL;
char *p, *l, *r;
int tmp, rc, maxrc = 0;
static faddr f, t;
faddr *o;
int result, flags, cost;
time_t mdate = 0L;
FILE *fp;
unsigned char buffer[0x0e];
char *subj = NULL;
result = fread(&buffer, 1, sizeof(buffer), pkt);
if (result == 0) {
Syslog('m', "Zero bytes message, assume end of pkt");
return 0;
}
switch(tmp = (buffer[0x01] << 8) + buffer[0x00]) {
case 0:
if (result == 2)
return 0;
else {
Syslog('!', "Junk after logical end of packet, skipped");
return 5;
}
case 2:
break;
default:
Syslog('!', "bad message type: 0x%04x",tmp);
return 2;
}
if (result != 14) {
Syslog('!', "Unexpected end of packet");
return 5;
}
memset(&f, 0, sizeof(f));
memset(&t, 0, sizeof(t));
f.node = (buffer[0x03] << 8) + buffer[0x02];
t.node = (buffer[0x05] << 8) + buffer[0x04];
f.net = (buffer[0x07] << 8) + buffer[0x06];
t.net = (buffer[0x09] << 8) + buffer[0x08];
flags = (buffer[0x0b] << 8) + buffer[0x0a];
cost = (buffer[0x0d] << 8) + buffer[0x0c];
/*
* Read the DateTime, toUserName, fromUserName and subject fields
* from the packed message. The stringlength is +1 for the right
* check. This is different then in ifmail's original code.
*/
if (aread(buf, sizeof(buf)-1, pkt)) {
if (strlen(buf) > 20)
Syslog('!', "date too long (%d) \"%s\"", strlen(buf), printable(buf, 0));
mdate = parsefdate(buf, NULL);
if (aread(buf, sizeof(buf)-1, pkt)) {
Syslog('!', "date not null-terminated: \"%s\"",buf);
return 3;
}
}
if (aread(buf, sizeof(buf)-1, pkt)) {
if (strlen(buf) > 36)
Syslog('!', "to name too long (%d) \"%s\"", strlen(buf), printable(buf, 0));
t.name = xstrcpy(buf);
if (aread(buf, sizeof(buf)-1, pkt)) {
if (*(p=t.name+strlen(t.name)-1) == '\n')
*p = '\0';
Syslog('!', "to name not null-terminated: \"%s\"",buf);
return 3;
}
}
if (aread(buf, sizeof(buf)-1, pkt)) {
if (strlen(buf) > 36)
Syslog('!', "from name too long (%d) \"%s\"", strlen(buf), printable(buf, 0));
f.name = xstrcpy(buf);
if (aread(buf, sizeof(buf)-1, pkt)) {
if (*(p=f.name+strlen(f.name)-1) == '\n')
*p = '\0';
Syslog('!', "from name not null-terminated: \"%s\"",buf);
return 3;
}
}
if (aread(buf, sizeof(buf)-1, pkt)) {
if (strlen(buf) > 72)
Syslog('!', "subject too long (%d) \"%s\"", strlen(buf), printable(buf, 0));
subj = xstrcpy(buf);
if (aread(buf, sizeof(buf)-1, pkt)) {
if (*(p=subj+strlen(subj)-1) == '\n')
*p = '\0';
subj = xstrcat(subj,(char *)"\\n");
subj = xstrcat(subj,buf);
Syslog('!', "subj not null-terminated: \"%s\"",buf);
return 3;
}
}
if (feof(pkt) || ferror(pkt)) {
Syslog('!', "Could not read message header, aborting");
return 3;
}
f.zone = p_from->zone;
t.zone = p_to->zone;
if ((fp = tmpfile()) == NULL) {
WriteError("$unable to open temporary file");
return 4;
}
/*
* Read the text from the .pkt file
*/
while (aread(buf,sizeof(buf)-1,pkt)) {
fputs(buf, fp);
/*
* Extract info from Origin line if found.
*/
if (!strncmp(buf," * Origin:",10)) {
p=buf+10;
while (*p == ' ') p++;
if ((l=strrchr(p,'(')) && (r=strrchr(p,')')) && (l < r)) {
*l = '\0';
*r = '\0';
l++;
if ((o = parsefnode(l))) {
f.point = o->point;
f.node = o->node;
f.net = o->net;
f.zone = o->zone;
if (o->domain)
f.domain=o->domain;
o->domain=NULL;
tidy_faddr(o);
}
} else
if (*(l=p+strlen(p)-1) == '\n')
*l='\0';
for (l=p+strlen(p)-1;*l == ' ';l--)
*l='\0';
orig = xstrcpy(p);
}
}
rc = importmsg(p_from, &f,&t,orig,subj,mdate,flags,cost,fp);
if (rc)
rc+=10;
if (rc > maxrc)
maxrc = rc;
fclose(fp);
if(f.name)
free(f.name);
f.name=NULL;
if(t.name)
free(t.name);
t.name=NULL;
if(f.domain)
free(f.domain);
f.domain=NULL;
if(t.domain)
free(t.domain);
t.domain=NULL;
if (subj)
free(subj);
subj = NULL;
if (orig)
free(orig);
orig = NULL;
if (feof(pkt) || ferror(pkt)) {
WriteError("Unexpected end of packet");
return 5;
}
return 1;
}