/* EMACS_MODES: !lnumb !fill */
#define NAME "frecv"
#define VERSION "2.1"


#include <stdio.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <dos.h>
#include <stdlib.h>
#include <time.h>


#define nl() printf("\n");

#define OK 0
#define ERROR 1
#define FATAL 2

#define EXTERNAL        0x0006      /* Main Type */

#define STX     '\002'        /* Start of text, to flag begin of files data */
#define EOT     '\004'        /* End of transmission */
#define LF	'\012'      /* Line Feed */
#define FF	'\014'      /* Form Feed (New Page) */

#define ERRLOG  "frecv.err"  /* File to log errors to */

#define MAXSYS  (unsigned short)65535  /* highest node number for WWIVnet */

#define MAXLINE 128         /* Maximum length of a line in a message */
#define MAXPATH 81          /* Maximum length of a DOS filesytem pathname */
#define MAXELM  30          /* Maximum number of elements for temp. array */
#define MSGLEN  33000       /* Max number of bytes for a single message */

#define FNAMELEN 13         /* number of bytes need to store a file name */

#define CONFITEMS 4        /* Number of items in the config file */


/* For Pattern Matching Routines */
#define TRUE		1
#define FALSE		0
#define ABORT		-1
#define NEGATE_CLASS	'^'

char array[MAXELM][MAXLINE];   /* temp array */
int error; /* error flag/counter */
unsigned short minor_type;
char message[MSGLEN];

FILE *fe;

/* From WWIVnet Doc */
typedef struct {
        unsigned short  tosys,         /* destination system */
                        touser,        /* destination user */
                        fromsys,       /* originating system */
                        fromuser;      /* originating user */
        unsigned short  main_type,     /* main message type */
                        minor_type;    /* minor message type */
        unsigned short  list_len;      /* # of entries in system list */
        unsigned long   daten;         /* date/time sent */
        unsigned long   length;        /* # of bytes of msg after header */
        unsigned short  method;        /* method of compression */
} net_header_rec;

char filename[FNAMELEN];  /* place to store filename */

typedef struct {
	char file[MAXPATH];        /* path for files directory */
	char external[MAXPATH];    /* path for external.net file */
	char temp[MAXPATH];         /* path for temp files */
	char minor[MAXPATH];       /* minor type */
} config;

net_header_rec nh;
config cf;


void main(int argc, char *argv[])
{

	int i,j;
	unsigned long length;
	char s[MAXLINE];


	error=0;

	colour(4);
	printf(" [%s:%s] Copyright (c) 1991 Andrew Gaunt. ",NAME,VERSION);
	colour(0);
	nl();
	colour(3);
	printf("Compiled %s %s",__DATE__,__TIME__);
	colour(0);
	nl();

	if (argc!=5){
		printf("usage: %s minor_type source destination work_dir\n",argv[0]);
		exit(0);
	}

	/* Open the error log file */
	if ( (fe=fopen(ERRLOG,"w")) == NULL ){
		colour(6);
		printf("FATAL: can't open error log %s for writing.",ERRLOG);
		colour(0);
		nl();
		myexit(FATAL);
	}
	minor_type=(unsigned short)atoi(argv[1]);
	if(extract(argv[2],argv[3],argv[4]) != NULL){
		myexit(FATAL);
	}
	colour(4);
	printf(" [%s:%s] Complete ",NAME,VERSION);
	colour(0);
	nl();
        exit(0);
}

extract(infile,outfile,work_dir)
char infile[];
char outfile[];
char work_dir[];
{
	FILE *fi;
	FILE *fo;
	FILE *fe;
	char extfile[MAXPATH];
	char s[MAXPATH];
	unsigned long count;
	unsigned num_read;
	int c;
	int i;
	short found;

	count=0;


	if( (fi=fopen(infile,"r+b")) == NULL){
		sprintf(s,"Can't read %s file.\n",infile);
		errlog(s);
		return(ERROR);
	}
	colour(3);
	printf("Reading %s.",infile);
	colour(0);
	nl();

	if( (fo=fopen(outfile,"w+b")) == NULL){
		sprintf(s,"Can't write %s file.\n",outfile);
		errlog(s);
		return(ERROR);
	}
	colour(3);
	printf("Writing %s.",outfile);
	colour(0);
	nl();
	nl();

	while(read_header(fi) == NULL){
/* 		putchar(FF); */
		colour(1);
		print_header();
		colour(0);
		nl();

		if( (nh.main_type==EXTERNAL) && (nh.minor_type==minor_type) ){

			num_read=read(fileno(fi),(char *)message,(unsigned)nh.length);
/* 			printf("Read returns %u.",num_read); /* DEBUG */
/* 			nl(); */
			strncpy(filename,message,FNAMELEN-1);
/* 			printf("Extracting: %s",filename); /* DEBUG */
/* 			nl(); */
			sprintf(extfile,"%s%s",work_dir,filename);
			if( (fe=fopen(extfile,"ab")) == NULL){
				sprintf(s,"Can't write to extract file %s.\n",extfile);
				errlog(s);
				return(ERROR);
			}
			colour(2);
			printf("file \"%s\", ",extfile);
			colour(0);

			found=0;count=0;
			for(i=0;i<num_read;i++){
				if(message[i]==STX && found==0){
					found=1;
					colour(1);
					printf("appending...");
					colour(0);
					continue;
				}
				if (found==1){
					fputc(message[i],fe);
					count++;
				}
			}
			if (found!=1){
				colour(6);
				printf("ERROR, no STX.");
				colour(0);
			}
			nl();
			colour(3);
			printf("%d bytes in message, %d bytes extracted.",i,count);
			colour(0);
			nl();
			nl();
			fclose(fe);
		}
		else{
			num_read=read(fileno(fi),(char *)message,(unsigned)nh.length);
/*  			printf("Read returns %u.",num_read); /* DEBUG */
			fflush(fo);
			write(fileno(fo),(void *)&nh,sizeof(net_header_rec));
 			fflush(fo);
			for(i=0;i<num_read;i++){
				fputc(message[i],fo);
			}
			colour(1);
			printf("%d bytes in message, nothing extracted.",i);
			colour(0);
			nl();
			nl();
			fclose(fe);
		}
	}
		
	fclose(fi);
	fclose(fo);
	fclose(fe);
	return(OK);	
}


/* Read a WWIVnet header, the system, major/minor types, and stuff */
read_header(fi)
FILE *fi;
{
	char s[MAXLINE];
/* 	printf("Reading WWIVnet header.\n"); /* DEBUG */
	fflush(fi);
	if(read(fileno(fi),(void *)&nh,sizeof(net_header_rec))==NULL){
		return(ERROR);
	}
	fflush(fi);
	return(OK);
}

/* Get the filename stored in the title */
read_filename(fi)
FILE *fi;
{
	char f[FNAMELEN];
/* 	printf("Reading filename.\n"); /* DEBUG */
	fflush(fi);
	read(fileno(fi),(char *)f,sizeof(f));
	fflush(fi);
	strncpy(filename,f,FNAMELEN-1);
	return(OK);
}

print_header()
{
	printf("From %u, ",nh.fromsys);
	printf("type %u-%u, ",nh.main_type,nh.minor_type);
/* 	printf("time=%u, msglen=%u",nh.daten,nh.length); */
	return(OK);
}

/*
print_header()
{
printf("WWIVnet Header Data:\n");
printf("\tTo system   : %u\n",nh.tosys);
printf("\tFrom system : %u\n",nh.fromsys);
printf("\tTo user     : %u\n",nh.touser);
printf("\tFrom user   : %u\n",nh.fromuser);
printf("\tMain type   : %u\n",nh.main_type);
printf("\tMinor type  : %u\n",nh.minor_type);
printf("\tList length : %u\n",nh.list_len);
printf("\tTime stamp  : %u\n",nh.daten);
printf("\tTotal len.  : %u",nh.length);
colour(0);
nl();
return(OK);
}
*/

errlog(s)
char *s[];
{
	fprintf(fe,"ERROR: %s",s);
	error++;
	return(OK);
}

myexit(r)
int r;
{
	char s[MAXLINE];

	/* close the error log */
	fclose(fe);
	if ( (fe=fopen(ERRLOG,"r")) == NULL ){
		printf("FATAL: can't open error log %s for reading.\n",ERRLOG);
		exit(FATAL);
	}
	printf("%d ERROR(S) have occuured:\n",error);
	while ( fgets(s,MAXLINE-1,fe)  ){
		printf("\t%s",s);
	}			
	fclose(fe);
	exit(r);
	return(OK);
}

int readable(f)
char f[];
{
  FILE *fp;
  if ( (fp=fopen(f,"r")) != NULL){
    fclose(fp);
    return(0);
  }
  fclose(fp);
  return(1);
}

colour(code)
short code;
{
  if (code<=7 && code>=0 ){
    printf("%c%d",'\003',code);

  }
  return(OK);
}
