/*****************************************************************************
 *
 * File ..................: tosser/importmsg.c
 * Purpose ...............: Import a message
 * Last modification date : 05-Jul-2001
 *
 *****************************************************************************
 * Copyright (C) 1997-2001
 *   
 * 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/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 "echoout.h"
#include "mkrfcmsg.h"
#include "importmsg.h"
#include "postnetmail.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
 */
extern	int	echo_in;		/* Echomail received		    */
extern	int	echo_imp;		/* Echomail imported		    */
extern	int	echo_out;		/* Echomail forwarded		    */
extern	int	echo_bad;		/* Bad echomail			    */
extern	int	echo_dupe;		/* Dupe echomail		    */
extern	char	*subj;			/* Message subject		    */
char		*msgid = NULL;		/* Message id string		    */

#define	MAXPATH	73
#define	MAXSEEN	70


void tidy_qualify(qualify **);
void fill_qualify(qualify **, fidoaddr, int, int);
void dlog_qualify(qualify **, char *);


void tidy_qualify(qualify **qal)
{
	qualify	*tmp, *old;

	for (tmp = *qal; tmp; tmp = old) {
		old = tmp->next;
		free(tmp);
	}
	*qal = NULL;
}



void fill_qualify(qualify **qal, fidoaddr aka, int orig, int insb)
{
	qualify		*tmp;

	tmp = (qualify *)malloc(sizeof(qualify));
	tmp->next     = *qal;
	tmp->aka      = aka;
	tmp->inseenby = insb;
	tmp->send     = ((!insb) && (!orig));
	tmp->orig     = orig;
	*qal = tmp;
}



void dlog_qualify(qualify **qal, char *msg)
{
	qualify	*tmpl;

	for (tmpl = *qal; tmpl; tmpl = tmpl->next) {
		Syslog('m', "%s InSB=%s Snd=%s Org=%s", 
			aka2str(tmpl->aka), tmpl->inseenby ? "True":"False",
			tmpl->send ? "True":"False",
			tmpl->orig ? "True":"False");
	}
}



/*
 * Import 1 message, forward if needed.
 * pkt_from, from, to, subj, orig, mdate, flags, cost, file
 *
 *  1 - Cannot open message base.
 *  2 - Cannot open mareas.data
 *  3 - Echomail without Origin line.
 *  4 - Echomail from unknown node, disconnected node.
 *  5 - Locking error.
 *
 * For echomail, the crc32 is calculated over the ^AREA kludge, subject, 
 * message date, origin line, message id.
 */
int importmsg(faddr *p_from, faddr *f, faddr *t, char *orig, time_t mdate, int flags, int cost, FILE *fp, off_t orig_off)
{
	char		*buf, *marea = NULL, *reply = NULL;
	char		*p, *q, *l, *r;
	int		echomail = FALSE, First = FALSE, email = FALSE;
	int		rc = 0, i, topt = 0, fmpt = 0, kludges = TRUE;
	faddr		*ta, *Faddr;
	int		result, dupe = FALSE, bad = FALSE;
	unsigned long	crc, crc2;
	char		sbe[16];
	sysconnect	Link;
	fa_list		*sbl = NULL, *ptl = NULL, *tmpl;
	qualify		*qal = NULL, *tmpq;
	FILE		*nfp, *qp;
	int		Known = FALSE, seenlen, oldnet;
	int		FirstLine;

	if (CFG.slow_util && do_quiet)
		usleep(1);

	memset(&Link, 0, sizeof(Link));
	msgid = NULL;

	/*
	 * 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;
	}

	crc = 0xffffffff;
	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 all sort of relevant kludges.
		 */
		if (FirstLine && (!strncmp(buf, "AREA:", 5))) {

			echo_in++;
			marea = xstrcpy(tu(buf + 5));

			if (orig == NULL) {
				Syslog('!', "Echomail without Origin line");
				echo_bad++;
				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++;
						bad = TRUE;
						free(marea);
						free(buf);
						return 4;
					}       
				} else {
					echo_bad++;
					bad = TRUE;
					free(buf);
					free(marea);
					return 4;
				}
			}
			crc = upd_crc32(buf, crc, strlen(buf));
			echomail = TRUE;
			free(marea);

			/*
			 * Check if node is allowed to enter echomail in this area.
			 */
			if (!bad) {
				bad = TRUE;
				First = TRUE;
				while (GetMsgSystem(&Link, First)) {
					First = FALSE;
					if ((p_from->zone == Link.aka.zone) &&
					    (p_from->net  == Link.aka.net) &&
					    (p_from->node == Link.aka.node)) {
						bad = FALSE;
						break;
					}
				}
				if (bad && (msgs.UnSecure || do_unsec)) {
					bad = FALSE;
					memset(&Link, 0, sizeof(Link));
				}
				if (bad) {
					Syslog('+', "Node %s not connected to area %s", ascfnode(p_from, 0x1f), msgs.Tag);
					free(buf);
					echo_bad++;
					return 4;
				} 

				if (Link.cutoff && !bad) {
					Syslog('+', "Echomail from %s in %s refused, cutoff", ascfnode(p_from, 0x1f), msgs.Tag);
					free(buf);
					bad = TRUE;
					echo_bad++;
					return 4;
				}
				if (!Link.receivefrom && !bad) {
					Syslog('+', "Echomail from %s in %s refused, read only", ascfnode(p_from, 0x1f), msgs.Tag);
					bad = TRUE;
					free(buf);
					echo_bad++;
					return 4;
				}

				if (CFG.toss_old) {
					if (((t_start - mdate) / 86400) > CFG.toss_old) {
						Syslog('+', "Rejecting msg: too old, %s", rfcdate(mdate));
						bad = TRUE;
						free(buf);
						echo_bad++;
						return 4;
					}
				}
			}

                        StatAdd(&msgs.Received, 1);
                        time(&msgs.LastRcvd);
                        StatAdd(&mgroup.MsgsRcvd, 1);
                        time(&mgroup.LastDate);
                        UpdateMsgs();
		}

		if (*buf != '\001')
			FirstLine = FALSE;

		if (!echomail) {

			/*
			 * Check for X-FTN- kludges, this could be gated email.
			 * This should be impossible.
			 */
			if (!strncmp(buf, "\001X-FTN-", 7)) {
				email = TRUE;
				Syslog('?', "Warning: detected ^aX-FTN- kludge in netmail");
			}

			/*
			 * Check DOMAIN and INTL kludges
			 */
			if (!strncmp(buf, "\001DOMAIN", 7)) {
				l = strtok(buf," \n");
				l = strtok(NULL," \n");
				p = strtok(NULL," \n");
				r = strtok(NULL," \n");
				q = strtok(NULL," \n");
				if ((ta = parsefnode(p))) {
					t->point = ta->point;
					t->node = ta->node;
					t->net = ta->net;
					t->zone = ta->zone;
					tidy_faddr(ta);
				}
				t->domain = xstrcpy(l);
				if ((ta = parsefnode(q))) {
					f->point = ta->point;
					f->node = ta->node;
					f->net = ta->net;
					f->zone = ta->zone;
					tidy_faddr(ta);
				}
				f->domain = xstrcpy(r);
			} else {
				if (!strncmp(buf, "\001INTL", 5)) {
					l = strtok(buf," \n");
					l = strtok(NULL," \n");
					r = strtok(NULL," \n");
					if ((ta = parsefnode(l))) {
						t->point = ta->point;
						t->node = ta->node;
						t->net = ta->net;
						t->zone = ta->zone;
						if (ta->domain) {
							if (t->domain) 
								free(t->domain);
							t->domain = ta->domain;
							ta->domain = NULL;
						}
						tidy_faddr(ta);
					}
					if ((ta = parsefnode(r))) {
						f->point = ta->point;
						f->node = ta->node;
						f->net = ta->net;
						f->zone = ta->zone;
						if (ta->domain) {
							if (f->domain) 
								free(f->domain);
							f->domain = ta->domain;
							ta->domain = NULL;
						}
						tidy_faddr(ta);
					}
				}
			}
			/*
			 * Now check FMPT and TOPT kludges
			 */
			if (!strncmp(buf, "\001FMPT", 5)) {
				p = strtok(buf, " \n");
				p = strtok(NULL, " \n");
				fmpt = atoi(p);
			}
			if (!strncmp(buf, "\001TOPT", 5)) {
				p = strtok(buf, " \n");
				p = strtok(NULL, " \n");
				topt = atoi(p);
			}

			if (!strncmp(buf, "\001MSGID: ", 8)) {
				msgid = xstrcpy(buf + 8);
				/*
				 *  Extra test to see if the mail comes from a pointaddress.
				 */
				l = strtok(buf," \n");
				l = strtok(NULL," \n");
				if ((ta = parsefnode(l))) {
					if (ta->zone == f->zone && ta->net == f->net && ta->node == f->node && !fmpt && ta->point) {
						Syslog('m', "Setting pointinfo (%d) from MSGID", ta->point);
						fmpt = f->point = ta->point;
					}
					tidy_faddr(ta);
				}
			}
		} /* if netmail */

		if (!strncmp(buf, "\001REPLYTO: ", 10))
			reply = xstrcpy(buf + 10);
		if (!strncmp(buf, "SEEN-BY:", 8)) {
			if (Link.aka.zone == msgs.Aka.zone) {
				p = xstrcpy(buf + 9);
				fill_list(&sbl, p, NULL, FALSE);
				free(p);
			} else
				Syslog('m', "Strip zone SB lines");
		}
		if (!strncmp(buf, "\001PATH:", 6)) {
			p = xstrcpy(buf + 7);
			fill_path(&ptl, p);
			free(p);
		}

	} /* end of checking kludges */

	/*
	 * Handle netmail
	 */
	if (!echomail) {
		/*
		 *  Only set point info if there was any info.
		 *  GoldED doesn't set FMPT and TOPT kludges.
		 */
		if (fmpt)
			f->point = fmpt;
		if (topt)
			t->point = topt;
		rc = postnetmail(fp, f, t, orig, subj, mdate, flags, TRUE);
		free(buf);
		return rc;
	} /* if !echomail */

	/*
	 * Handle echomail
	 */
	if (echomail && (!bad)) {
		/*
		 * First, further dupe checking.
		 */
		crc = upd_crc32(subj, crc, strlen(subj));

		if (orig == NULL)
			Syslog('!', "No origin line found");
		else
			crc = upd_crc32(orig, crc, strlen(orig));

		crc = upd_crc32((char *)&mdate, crc, sizeof(mdate));

		if (msgid != NULL) {
			crc = upd_crc32(msgid, crc, strlen(msgid));
		} else {
			if (check_dupe) {
				/*
				 *  If a MSGID is missing it is possible that dupes from some offline
				 *  readers slip through because these readers use the same date for
				 *  each message. In this case the message text is included in the
				 *  dupecheck. Redy Rodriguez.
				 */
				rewind(fp);
				while ((fgets(buf, 2048, fp)) != NULL) {
					Striplf(buf);
					if (strncmp(buf, "---", 3) == 0)
						break;
					if ((strncmp(buf, "\001", 1) != 0 ) && (strncmp(buf,"AREA:",5) != 0 )) 
						crc = upd_crc32(buf, crc , strlen(buf));        
				}     
			}   
		}

		if (check_dupe)
			dupe = CheckDupe(crc, D_ECHOMAIL, CFG.toss_dupes);
		else
			dupe = FALSE;
		if (dupe)
			echo_dupe++;
	}

	if ((echomail) && (!bad) && (!dupe) && (!msgs.UnSecure) && (!do_unsec)) {

		/*
		 * Check if the message is for us. Don't check point address,
		 * echomail messages don't have point destination set.
		 */
		if ((msgs.Aka.zone != t->zone) || (msgs.Aka.net != t->net) || (msgs.Aka.node != t->node)) {
			bad = TRUE;
			/*
			 * If we are a hub or host and have all our echomail
			 * connected to the hub/host aka, echomail from points
			 * under a nodenumber aka isn't accepted. The match
			 * must be further tested.
			 */
			if ((msgs.Aka.zone == t->zone) && (msgs.Aka.net == t->net)) {
				for (i = 0; i < 40; i++) {
					if ((CFG.akavalid[i]) &&
					    (CFG.aka[i].zone == t->zone) &&
					    (CFG.aka[i].net  == t->net) &&
					    (CFG.aka[i].node == t->node))
						bad = FALSE; /* Undo the result */
				}
			}
		}
		if (bad) {
			echo_bad++;
			WriteError("Msg in %s not for us (%s) but for %s", msgs.Tag, aka2str(msgs.Aka), ascfnode(t,0x1f));
		}
	}

	if ((echomail) && (!bad) && (!dupe)) {

		if (msgs.Aka.zone != Link.aka.zone) {
			/*
			 * If it is a zonegated echomailmessage the SEEN-BY lines
			 * are stripped off including that of the other zone's
			 * gate. Add the gate's aka to the SEEN-BY
			 */
			Syslog('m', "Gated echomail, clean SB");
			tidy_falist(&sbl);
			sprintf(sbe, "%u/%u", Link.aka.net, Link.aka.node);
			Syslog('m', "Add gate SB %s", sbe);
			fill_list(&sbl, sbe, NULL, FALSE);
		}

		/*
		 * Add more aka's to SEENBY if in the same zone as our system.
		 * When ready filter dupe's, there is at least one.
		 */
		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))) {
				sprintf(sbe, "%u/%u", CFG.aka[i].net, CFG.aka[i].node);
				fill_list(&sbl, sbe, NULL, FALSE);
			}
		}
		uniq_list(&sbl);
	}

	/*
	 * Add our system to the path for later export.
	 */
	sprintf(sbe, "%u/%u", msgs.Aka.net, msgs.Aka.node);
	fill_path(&ptl, sbe);

	if (echomail) {
		/*
		 * Build a list of qualified systems to receive this message.
		 * Complete the SEEN-BY lines.
		 */
		First = TRUE;
		while (GetMsgSystem(&Link, First)) {
			First = FALSE;
			if ((Link.aka.zone) && (Link.sendto) && (!Link.pause) && (!Link.cutoff)) {
				Faddr = fido2faddr(Link.aka);
				fill_qualify(&qal, Link.aka, ((p_from->zone  == Link.aka.zone) && 
				      (p_from->net   == Link.aka.net) && (p_from->node  == Link.aka.node) && 
				      (p_from->point == Link.aka.point)), in_list(Faddr, &sbl, FALSE));
				tidy_faddr(Faddr);
			}
		}

		/*
		 *  Add SEEN-BY for nodes qualified to receive this message.
		 *  When ready, filter the dupes and sort the SEEN-BY entries.
		 */
		for (tmpq = qal; tmpq; tmpq = tmpq->next) {
			if (tmpq->send) {
				sprintf(sbe, "%u/%u", tmpq->aka.net, tmpq->aka.node);
				fill_list(&sbl, sbe, NULL, FALSE);
			}
		}
		uniq_list(&sbl);
		sort_list(&sbl);

		/*
		 *  Create a new tmpfile with a copy of the message
		 *  without original PATH and SEENBY lines, add the
		 *  new PATH and SEENBY lines.
		 */
		rewind(fp);
		if ((nfp = tmpfile()) == NULL) {
			WriteError("$Unable to open tmpfile");
		}
		while ((fgets(buf, 2048, fp)) != NULL) {
			Striplf(buf);
			fprintf(nfp, "%s", buf);
			/*
			 * Don't write SEEN-BY and PATH lines
			 */
			if (strncmp(buf, " * Origin:", 10) == 0)
				break;
			fprintf(nfp, "\n");
		}

		/*
		 * Now add new SEEN-BY and PATH lines
		 */
		seenlen = MAXSEEN + 1;
		/*
		 * Ensure that it will not match for 
		 * the first entry.
		 */
		oldnet = sbl->addr->net - 1;
		for (tmpl = sbl; tmpl; tmpl = tmpl->next) {
			if (tmpl->addr->net == oldnet)
				sprintf(sbe, " %u", tmpl->addr->node);
			else
				sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node);
			oldnet = tmpl->addr->net;
			seenlen += strlen(sbe);
			if (seenlen > MAXSEEN) {
				seenlen = 0;
				fprintf(nfp, "\nSEEN-BY:");
				sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node);
				seenlen = strlen(sbe);
			}
			fprintf(nfp, "%s", sbe);
		}

		seenlen = MAXPATH + 1;
		/* 
		 * Ensure it will not match for the first entry
		 */
		oldnet = ptl->addr->net - 1;
		for (tmpl = ptl; tmpl; tmpl = tmpl->next) {
			if (tmpl->addr->net == oldnet)
				sprintf(sbe, " %u", tmpl->addr->node);
			else
				sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node);
			oldnet = tmpl->addr->net;
			seenlen += strlen(sbe);
			if (seenlen > MAXPATH) {
				seenlen = 0;
				fprintf(nfp, "\n\001PATH:");
				sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node);
				seenlen = strlen(sbe);
			}
			fprintf(nfp, "%s", sbe);
		}
		fprintf(nfp, "\n");
		fflush(nfp);
		rewind(nfp);

		/*
		 * Import this message.
		 */
		if (bad) {
			if (strlen(CFG.badboard) == 0) {
				Syslog('+', "Killing bad message");
				tidy_falist(&sbl);
				tidy_falist(&ptl);
				tidy_qualify(&qal);
				free(buf);
				return 0;
			} else {
				if ((result = Msg_Open(CFG.badboard)))
					Syslog('+', "Tossing in bad board");
			}
		} else if (dupe) {
			if (strlen(CFG.dupboard) == 0) {
				Syslog('+', "Killing dupe message");
				tidy_falist(&sbl);
				tidy_falist(&ptl);
				tidy_qualify(&qal);
				free(buf);
				return 0;
			} else {
				if ((result = Msg_Open(CFG.dupboard)))
					Syslog('+', "Tossing in dupe board");
			}
		} else {
			result = Msg_Open(msgs.Base);
		}
		if (!result) {
			WriteError("Can't open JAMmb %s", msgs.Base);
			tidy_falist(&sbl);
			tidy_falist(&ptl);
			tidy_qualify(&qal);
			free(buf);
			return 1;
		}

		if (Msg_Lock(30L)) {
			if ((!dupe) && (!bad))
				echo_imp++;

			if (!do_quiet) {
				colour(3, 0);
				printf("\r%6u => %-40s\r", echo_in, msgs.Name);
				fflush(stdout);
			}

			Msg_New();

			/*
			 * Fill subfields
			 */
			strcpy(Msg.From, f->name);
			strcpy(Msg.To, t->name);
			strcpy(Msg.FromAddress, ascfnode(f,0x1f));
			strcpy(Msg.Subject, subj);
			Msg.Written = mdate;
			Msg.Arrived = time(NULL);
			Msg.Echomail = TRUE;

			/*
			 * These are the only usefull flags in echomail
			 */
			if ((flags & M_PVT) && ((msgs.MsgKinds == BOTH) || (msgs.MsgKinds == PRIVATE)))
				Msg.Private = TRUE;
			if (flags & M_FILE)
				Msg.FileAttach = TRUE;

			/*
			 * Set MSGID and REPLYID crc.
			 */
			if (msgid != NULL) {
				crc2 = -1;
				Msg.MsgIdCRC = upd_crc32(msgid, crc2, strlen(msgid));
			}
			if (reply != NULL) {
				crc2 = -1;
				Msg.ReplyCRC = upd_crc32(reply, crc2, strlen(reply));
			}

			/*
			 * Start write the message
			 * If not a bad or dupe message, eat the first
			 * line (AREA:tag).
			 */
			rewind(nfp);
			if (!dupe && !bad)
				fgets(buf , 256, nfp);
			Msg_Write(nfp);
			Msg_AddMsg();
			Msg_UnLock();
			Msg_Close();
		} else {
			Syslog('+', "Can't lock msgbase %s", msgs.Base);
			Msg_UnLock();
			Msg_Close();
			tidy_falist(&sbl);
			tidy_falist(&ptl);
			tidy_qualify(&qal);
			free(buf);
			return 5;
		}

		/*
		 * Forward to other links
		 */
		if ((!dupe) && (!bad)) {
			/*
			 * Now start exporting this echomail.
			 */
			for (tmpq = qal; tmpq; tmpq = tmpq->next) {
				if (tmpq->send) {
					if (SearchNode(tmpq->aka)) {
						StatAdd(&nodes.MailSent, 1L);
						UpdateNode();
						SearchNode(tmpq->aka);
					}
					echo_out++;
					EchoOut(p_from, tmpq->aka, nfp, flags, cost, mdate);
				}
			}

			/*
			 *  Gate to newsserver
			 */
			if (strlen(msgs.Newsgroup)) {
				rewind(nfp);
				qp = tmpfile();
			        while ((fgets(buf, 2048, nfp)) != NULL) {
					Striplf(buf);
					if (kludges && (buf[0] != '\001') && strncmp(buf, "AREA:", 5)) {
						kludges = FALSE;
						q = xstrcpy(Msg.From);
						for (i = 0; i < strlen(q); i++)
							if (q[i] == ' ')
								q[i] = '_';
						fprintf(qp, "From: %s@%s\n", q, ascinode(f, 0x1f));
						fprintf(qp, "Subject: %s\n", Msg.Subject);
						fprintf(qp, "To: %s\n", Msg.To);
						fprintf(qp, "\n");
					}
					fprintf(qp, "%s\n", buf);
				}
				rewind(qp);
				most_debug = TRUE;
				mkrfcmsg(f, t, subj, orig, mdate, flags, qp, orig_off, FALSE);
				most_debug = FALSE;
				fclose(qp);
			}
		}
		fclose(nfp);
	}

	/*
	 * Free memory used by SEEN-BY, ^APATH and Qualified lines.
	 */
	tidy_falist(&sbl);
	tidy_falist(&ptl);
	tidy_qualify(&qal);

	if (rc < 0) 
		rc =-rc;
	free(buf);
	if (reply)
		free(reply);
	return rc;
}



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;
}