#include <ascii.h>
#include "fido.h"
#include "fidomem.h"
#include <xfbuf.h>
#include "proto.h"

/* Unpack a message packet, put the messages into the mail area. Return true 
if it unpacked OK. */

int unpacket(fn)
char *fn;			/* packet filename */
{
int file,i,n;
char *cp,buff[SS];
struct _pkthdr pkthdr;		/* header from incoming packet */
struct _node d;			/* "clean" source node, from pkt header */

	file= open(fn,0);
	if (file == -1) {			/* packet disappeared? */
		clprintf(SM+45,fn);
		return(0);
	}

	n= read(file,&pkthdr,sizeof(struct _pkthdr));
	if (n != sizeof(struct _pkthdr)) {	/* complain about bad packets */
		if (n) clprintf(SM+106,fn,n);
		close(file);
		delete(fn);			/* kill it */
		return(1);
	}

	d.zone= pkthdr.orig_zone;
	if (! d.zone) d.zone= id.zone;
	d.net= pkthdr.orig_net;
	d.number= pkthdr.orig_number;
	d.point= 0;

	clprintf(SM+107,str_node(&d));		/* got a packet */
	n= 0;
	while ((i= unpmsg(file)) > 0) ++n;	/* unpack each msg, */
	close(file);				/* close the file */
	clprintf(SM+108,n);			/* number of messages */

/* If a bad packet, rename the .IN file to .BAD. Don't overwrite any existing
.BAD files -- locate the highest .BAD filename already there first. */

	if (i != 0) {				/* if a bad packet */
		strip_path(buff,fn);		/* rename <pathname>\xxx.IN */
		sprintf(&buff[strlen(buff)],0,"%d.BAD", /* to <path>\yyy.BAD */
		    next_bad());
		rename(fn,buff);		/* rename(old,new) */
		clprintf(SM+109,fn,buff);
		return(0);			/* something went wrong */
	}
	delete(fn);				/* done, kill it */

/* If any files were attached, add them to FILES.BBS. */

	strcpy(buff,fn);			/* create the file list name */
	for (cp= buff; *cp; ++cp) 		/* find the dot "." */
		if (*cp == '.') break;
	strcpy(cp,".FLI");			/* make that .FLI */

	unfile(buff,&d);			/* process any .FLI files */
	return(1);
}

/* Return the next .BAD file number. */

static next_bad() {
int i,n;
struct _xfbuf xfbuf;
char buff[SS];

	n= i= xfbuf.s_attrib= 0;
	makefname(buff,"*.BAD");
	while (_find(buff,i++,&xfbuf)) {
		if (atoi(xfbuf.name) > n) n= atoi(xfbuf.name);
	}
	return(n + 1);
}

/* Process a .FLI file and add the names to FILES.BBS. Return 0 if error. */

unfile(fn,d)
char *fn;		/* .FLI file name */
struct _node *d;	/* who it's from */
{
int file,f,n;
char c,buff[SS],ln[SS];

	file= open(fn,0);
	if (file == -1) return(1);

	makefname(buff,"FILES.BBS");
	f= append(buff);			/* open/create FILES.BBS */
	if (f == -1) {
		clprintf(SM+10,buff);		/* "cant create..." */
		close(file);			/* oops */
		return(0);
	}
	while (1) {				/* process all filenames */
		n= 0;				/* filename length */
		while (read(file,&c,1)) {	/* get a filename */
			if (delim(c)) {		/* if a blank etc */
				if (n) break;	/* stop if end of filename */
				continue;	/* else leading garbage */
			}
			ln[n++]= c;		/* filename character */
		}
		ln[n]= NUL;			/* terminate the line */
		if (! n) break;			/* file empty */

		cpyarg(ln,strip_path(buff,ln));	/* skip past the pathname */
		ln[14]= NUL;			/* clip long names */
		stoupper(ln);			/* make upper case */
		if (! is_us(d)) sprintf(&ln[strlen(ln)],SM+111,str_node(d));
		strcat(ln,"\r\n");
		write(f,ln,strlen(ln));		/* write it, */
		clputs("   "); clputs(ln);	/* log it */
	}
	close(f);
	close(file);
	delete(fn);				/* done, kill it */
	return(1);
}

/* Unpack a message from the message file; the message type (0 is end-of-packet)
or -1 if error or the message type. */

unpmsg(file)
int file;
{
int msgtype;
char *p;
char c,name[SS],buff[SS];
int f,n,i;

	msgtype= 0;				/* in case read error, */
	read(file,&msgtype,sizeof(msgtype));

	switch (msgtype) {
		case 0:
			return(0);		/* type == end of packet */
			break;

		case 1:				/* incompatible version */
			clprintf(SM+112);
			return(-1);
			break;

		case 2:				/* v10 - v11 */
			break;

		default:			/* unknown msg type */
			clprintf(SM+113,msgtype);
			return(-1);
			break;
	}

	p= (char *) &msg;			/* clear the sucker out */
	for (n= 0; n < sizeof(struct _msg); ++n) *p++= NUL;

	msg.orig_node= cgeti(file);		/* v10 ... */
	msg.dest_node= cgeti(file);
	msg.orig_net= cgeti(file);
	msg.dest_net= cgeti(file);		/* ... v10 */

	msg.attr= cgeti(file);			/* get attributes */
	msg.cost= cgeti(file);			/* get msg cost as entered */
	msg.attr &= MSGMASK;			/* strip some bits */

	if (cgets(file,msg.date,sizeof(msg.date)) == 0) return(-1);
	if (cgets(file,msg.to,sizeof(msg.to)) == 0) return(-1);
	if (cgets(file,msg.from,sizeof(msg.from)) == 0) return(-1);
	if (cgets(file,msg.subj,sizeof(msg.subj)) == 0) return(-1);

	if (shared()) {				/* if shared or multitasking */
		msgcount();			/* recount messages */
	}
	sprintf(buff,0,"%d.MSG",*msg_highest() + 1);
	makemname(name,buff);
	f= creat(name,2);			/* create the message file, */
	if (f == -1) {
		clprintf(SM+10,name);		/* "can't create" */
		frc_abort();
	}

	++*msg_highest();			/* account for it */
	++*msg_total();

	if (write(f,&msg,sizeof(struct _msg)) != sizeof(struct _msg)) {
		clprintf(SM+115,name);		/* "disk full!" */
		frc_abort();
	}
	n= 0;
	while (c= cgetc(file)) {		/* copy the msg text */
		if (write(f,&c,1) != 1) {	/* byte by byte */
			clprintf(SM+115,name);	/* "disk full!" */
			frc_abort();
		}
	}
	write(f,"",1);				/* terminating null */
	close(f);
	return(msgtype);
}

/* Read a string from the packet file, including the null. Return 0 if we hit
EOF. Make sure we dont write too many characters into the string; toss the
extra chars from the string if necessary. */

cgets(f,s,len)
int f;
char *s;
int len;
{

int n;
char c;

	do {
		n= read(f,&c,1);		/* read one, */
		if (len > 1) {			/* if string not full */
			*s++= c;		/* store it */
			*s= NUL;		/* (terminate the string) */
			--len;
		}
	} while (n && c);
	return(n);
}
/* Read an integer from the packet file. */

cgeti(f)
int f;
{
int i;

	read(f,&i,sizeof(i));
	return(i);
}
/* Read a character from the packet file. Return null if EOF or null read. */

cgetc(file)
int file;
{
char c;

	if (read(file,&c,1) == 0) return(NUL);
	else return(c);
}
