
/* Be sure to run this program from the file_storage_directory_spec! */

/*
This program scans the message files in the netmail directory looking
for messages addressed to it (FIDO_FTP as the name-to).  Any messages
which are null or of unrecognized format will engender a "help" message
which is sent to the originator of the message.  Messages which are
requests are processed immediately.

The subject of any received message is ignored for now.

Message format:  - LIST obtains a list of internet sites (file-attached)
		 - USERNAME=x sets the username to be used when FTPing
		 - PASSWORD=x sets the password to be used when FTPing
		 - SITE=x connects to that Internet site
		 - DIR=x gets a listing of the directory x (omit x for root dir)
		 - GET=x gets that file (i.e. GET=/pub/msdos/00-index.lst)
*/


#define MAX_MSGS_TO_SCAN 250  /* We scan messages from 1 to this  */
							  /*  number for the name FIDO_FTP.   */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <conio.h>
#include <time.h>
#include <dos.h>  /* Dos-specific functions are used to get date/time. */

#include "common.h"
#include "modem.h"     /* Routines for accessing the modem. */
#include "fidonet.h"

/* Prototypes. */
int read_character_from_message(void);
int init_message_body_file(void);
int parse_message_line(void);
void process_this_message(void);
void comm_port_open(void);
void comm_port_close(void);
int vax_logon(void);
int vax_logon_attempt(void);
void vax_logoff(void);
void trace_count(void);
void trace_stop_all(void);


#define ERRORLEVEL_SUCCESS       0
#define ERRORLEVEL_BAD_PARAMETER 1
#define ERRORLEVEL_CONFIGURATION 2
#define ERRORLEVEL_FATAL         3
#define ERRORLEVEL_RING          4   /* Returned when a call is coming in. */

FILE *config_file,*incoming_file;
FILE *flag_file;  /* Program leaves behind if it couldn't log onto VAX; deletes if it process all messages ok. */
int message_number = 0;    /* The message number to open; we search  */
						   /*  the first MAX_MSGS_TO_SCAN messages.  */
int errcode,        /* Used for holding results of indexed file engine calls. */
  modem_port_no,    /* Hold this info. from the config file. */
  result;           /* This is used to hold the result of memcmp() calls. */
char temp_string[128],temp_string_2[128],
	CR_string[2],   /* This gets initialized to be a CR we can append to lines. */
	DOUBLE_QUOTE_string[3], CTRL_A_string[2], CTRL_Y_string[2],
	CTRL_U_string[2],
  parsed_message_line[128],parsed_keyword[128],parsed_value[128],  /* These are used for parsing message lines. */
  message_file_suffix[]=".msg",
  config_file_name[64],help_file_name[64],sitelist_file_name[64],
  incoming_file_name[64],netmail_directory_spec[64],
  file_storage_directory_spec[64],  /* Where files from the vax / to the requester are stored. */
  modem_port_string[4],   /* Holds port modem is attached to. */
  the_sitename[64], ftp_username[64], ftp_password[64],
  vax_phone_number[16]="",vax_account_name[16],vax_account_password[16],
  vax_prompt_string[]="SHIT",transfer_filename[16],
  logged_onto_vax_flag=0, /* Remembers status. */
	flag_file_name[16]="fido_ftp.flg",
	directory_listing_filename[64];  /* This is where we will capture the directory listing to. */
div_t results;  /* Used for splitting integers into separate bytes. */


/*-------------------------- Modem routines -------------------------------*/

void comm_port_open()
{
modem_port = modem_port_no + 1;
initSerial(modem_port,modem_speed,modem_parity,modem_bits,modem_stopbits);
}

void comm_port_close()
{
deinitSerial(0);   /* ...turning off DTR. */
}

/*---------------------------- Subroutines --------------------------------*/

int vax_logon()  /* Return non-zero if we have trouble logging on. */
{
char retry_count=4;  /* We decrement this thing each time we try to log on. */
int result;
while (retry_count--)
  {
  result = vax_logon_attempt();
  if (!result)
    {
    logged_onto_vax_flag = 1;
    return(0);    /* Successful; return 0. */
    }
	common_debug_message(common_debug_level_current,"Resetting modem after logon attempt.");
  comm_port_close();   /* Hang up for sure! */
  wait(1);
  comm_port_open();
  }
return(1);        /* Unsuccessful.         */
}

int vax_logon_attempt() /* Return non-zero if we have trouble logging on. */
{
common_debug_message(common_debug_level_current,"vax_logon()");
wait(1);
trash_modem_output(modem_port_no,common_debug_level_current);
send_to_modem(modem_port_no,CR_string);
wait(1);
send_to_modem(modem_port_no,CR_string);
wait(1);
send_to_modem(modem_port_no,"AT");
send_to_modem(modem_port_no,CR_string);
if (waitfor(modem_port_no,"OK",1,common_debug_level_current))
  {
	common_debug_message(common_debug_level_current,"?Didn't get  OK  from modem after sending AT to it.");
	return(1);
	}
wait(1);
trash_modem_output(modem_port_no,common_debug_level_current);
if (kbhit())               /* Did the user hit a key? */
  {
  comm_port_close();
  exit(ERRORLEVEL_RING);
  }
send_to_modem(modem_port_no,"ATD");
send_to_modem(modem_port_no,vax_phone_number);
send_to_modem(modem_port_no,CR_string);

trace_start("CONNECT");
trace_start("NO DIAL TONE");
if (waitfor_any_trace(modem_port_no,30,common_debug_level_current))
  {
  trace_stop_all();
	common_debug_message(common_debug_level_current,"?Didn't get CONNECT, RING, or NO DIAL TONE from modem after dialing.");
	return(1);
  }
if (trace_fired("NO DIAL TONE"))
  {
  trace_stop_all();
  comm_port_close();
  exit(ERRORLEVEL_RING);  /* This was probably because of a collision. */
  }
trace_stop_all();  /* If we got here, CONNECT was detected. */
wait(2);
trash_modem_output(modem_port_no,common_debug_level_current);
send_to_modem(modem_port_no,CR_string);
wait(1);
trash_modem_output(modem_port_no,common_debug_level_current);
send_to_modem(modem_port_no,CR_string);
/*   TEST
if (waitfor(modem_port_no,"username>",2,common_debug_level_current))
  {
  common_debug_message(common_debug_level_current,"?Couldn't get terminal server prompt  username>  after sending CRs.");
  return(1);
  }
send_to_modem(modem_port_no,"acm");
send_to_modem(modem_port_no,CR_string);
*/
if (waitfor(modem_port_no,"Local>",2,common_debug_level_current))
  {
	common_debug_message(common_debug_level_current,"?Couldn't get terminal server prompt  Local  after sending CRs.");
  return(1);
  }
send_to_modem(modem_port_no,"c");
send_to_modem(modem_port_no,CR_string);
if (waitfor(modem_port_no,"Username:",7,common_debug_level_current))
  {
  common_debug_message(common_debug_level_current,"?Couldn't get  Username:  after sending  c  to terminal server.");
  return(1);
  }
send_to_modem(modem_port_no,vax_account_name);
send_to_modem(modem_port_no,"/command=FTP_LOGIN.COM");
send_to_modem(modem_port_no,CR_string);
if (waitfor(modem_port_no,"Password:",10,common_debug_level_current))
  {
  common_debug_message(common_debug_level_current,"?Didn't get  Password:  after sending account name to login.");
  return(1);
  }
send_to_modem(modem_port_no,vax_account_password);
send_to_modem(modem_port_no,CR_string);
wait(1);
send_to_modem(modem_port_no,CTRL_U_string);
send_to_modem(modem_port_no,CR_string);  /* Send another return because the "attach/[YES]" prompt may have appeared. */
wait(2);
trash_modem_output(modem_port_no,common_debug_level_current);
send_to_modem(modem_port_no,CTRL_U_string);
send_to_modem(modem_port_no,"quit");    /* In case we're stuck in FTP because we reattached. */
send_to_modem(modem_port_no,CR_string);
wait(1);
if (waitfor(modem_port_no,vax_prompt_string,30,common_debug_level_current))  /* Wait for our unique prompt string. */
  {
  send_to_modem(modem_port_no,CTRL_Y_string);
  wait(1);
  if (waitfor(modem_port_no,vax_prompt_string,3,common_debug_level_current))
    {
    common_debug_message(common_debug_level_current,"?Didn't get DCL prompt.");
    return(1);
    }
  }
wait(1);
trash_modem_output(modem_port_no,common_debug_level_current);
return(0);
}

void vax_logoff()
{
common_debug_message(common_debug_level_current,"vax_logoff()");
send_to_modem(modem_port_no,"quit");  /* In case we got stuck running FTP. */
send_to_modem(modem_port_no,CR_string);
wait(1);
send_to_modem(modem_port_no,CTRL_Y_string);
wait(1);
send_to_modem(modem_port_no,"lo");
send_to_modem(modem_port_no,CR_string);
if (waitfor(modem_port_no,"Local>",5,common_debug_level_current))
	common_debug_message(common_debug_level_current,"!A timeout occurred waiting for  Local  after invoking  byebye.com");
send_to_modem(modem_port_no,"lo");
send_to_modem(modem_port_no,CR_string);
if (waitfor(modem_port_no,"NO CARRIER",7,common_debug_level_current))
	common_debug_message(common_debug_level_current,"!A timeout occurred waiting for  NO CARRIER  after sending  lo  to term svr");
comm_port_close();    /* Hang up for sure. */
wait(1);
comm_port_open();
logged_onto_vax_flag = 0;
common_debug_message(common_debug_level_current,"End of vax_logoff()");
}


/*----------------------- Program functions ------------------------*/
int ftp_attach_to_site()  /* Returns 0 if ok, 1 if invalid site, 2 if links are down. */
{
if (!the_sitename[0])     /* Null sitename? */
  return(1);
send_to_modem(modem_port_no,CTRL_Y_string);
send_to_modem(modem_port_no,CTRL_Y_string);
wait(1);
send_to_modem(modem_port_no,"ftp ");        /* Try to hook up to the site. */
send_to_modem(modem_port_no,the_sitename);
wait(1);
send_to_modem(modem_port_no," /binary /username=");
send_to_modem(modem_port_no,DOUBLE_QUOTE_string);
send_to_modem(modem_port_no,ftp_username);
send_to_modem(modem_port_no,DOUBLE_QUOTE_string);
wait(1);
send_to_modem(modem_port_no," /password=");
send_to_modem(modem_port_no,DOUBLE_QUOTE_string);
send_to_modem(modem_port_no,ftp_password);
send_to_modem(modem_port_no,DOUBLE_QUOTE_string);
send_to_modem(modem_port_no,CR_string);
trace_start("opened");
trace_start("Timeout");
trace_start("Unknown");
if (waitfor_any_trace(modem_port_no,75,common_debug_level_current))  /* Timeout? */
  {
  trace_stop_all();
  send_to_modem(modem_port_no,"quit");
  send_to_modem(modem_port_no,CR_string);
  wait(1);
  send_to_modem(modem_port_no,CTRL_Y_string);
  send_to_modem(modem_port_no,CTRL_Y_string);
  return(2);
  }
if (trace_fired("Timeout"))
  {
  trace_stop_all();
  send_to_modem(modem_port_no,"quit");
  send_to_modem(modem_port_no,CR_string);
  wait(1);
  send_to_modem(modem_port_no,CTRL_Y_string);
  send_to_modem(modem_port_no,CTRL_Y_string);
  return(2);
  }
if (trace_fired("Unknown"))
  {
  trace_stop_all();
  send_to_modem(modem_port_no,"quit");
  send_to_modem(modem_port_no,CR_string);
  wait(1);
  send_to_modem(modem_port_no,CTRL_Y_string);
  send_to_modem(modem_port_no,CTRL_Y_string);
  return(1);
  }
trace_stop_all();
if (waitfor(modem_port_no,">",20,common_debug_level_current))
  return(2);  /* Just leave message here so I notice it or something. */
wait(1);
trash_modem_output(modem_port_no,common_debug_level_current);
return(0);
}

int ftp_get_file_from_site(char *filespec_to_get)  /* Returns 0 if ok (file is attached), 1 if bad site, 2 if bad filespec, 3 if program error, 4 if couldn't even log on, 5 if links are down. */
{
FILE *transfer_file; /* Used for checking for existence of XFERFILE.xxx files.*/
char temp_string[64];
int unique_number=0,result_code;
if (!logged_onto_vax_flag)    /* Are we already logged onto the Vax?    */
  if (vax_logon())  /* Problem logging onto the Vax?                    */
    return(4);      /*   Don't do anything or mark message as received. */
result_code = ftp_attach_to_site();
if (result_code==2)
  return(5);            /* Indicate that links to site are probably down. */
if (result_code==1)
  return(1);
while (1)                 /* Search for an unused XFERFILE.xxx name.  */
  {
  strcpy(transfer_filename,"XFERFILE.");
  itoa(unique_number++,temp_string,10);
  strcat(transfer_filename,temp_string);
  transfer_file = fopen(transfer_filename,"rb");
  if (transfer_file == NULL)   /* Found a preexisting file? */
    break;
  fclose(transfer_file);     /*  Close and look for next. */
  /* Go back and try the next number, which is already in unique_number. */
  }
common_debug_message_w_no(common_debug_level_current,"Transferring to local file XFERFILE.",unique_number-1);
send_to_modem(modem_port_no,"get ");  /* Send the FTP "get" command. */
send_to_modem(modem_port_no,filespec_to_get);
send_to_modem(modem_port_no,CR_string);
wait(1);
send_to_modem(modem_port_no,transfer_filename);
send_to_modem(modem_port_no,CR_string);
trace_start("Opening");
trace_start("No such");
trace_start("connection");
if (waitfor_any_trace(modem_port_no,10,common_debug_level_current))  /* Success or failure? */
  {
  trace_stop_all();
  common_debug_message(common_debug_level_current,"Didn't get indication that transfer had begin.");
  send_to_modem(modem_port_no,"quit");
  send_to_modem(modem_port_no,CR_string);
  return(3);   /* Didn't get either expected message. */
  }
if (trace_fired("No such"))
  {
  trace_stop_all();
  common_debug_message(common_debug_level_current,"Remote said no such file exists.");
  send_to_modem(modem_port_no,"quit");
  send_to_modem(modem_port_no,CR_string);
  return(2);   /* Bad filespec. */
  }
common_debug_message(common_debug_level_current,"Remote FTP site has started transfer.");
trace_stop_all();   /* We got one of the xfer-started messages. */
/* Here we assume that the xfer is in progress.  If a file is     */
/*  longer than 300 seconds, then we will assume the xfer failed. */
if (waitfor(modem_port_no,"complete",300,common_debug_level_current))  /* Did we get the "successful" message?  Xfers are limited to 300 seconds by this timeout. */
  {
  common_debug_message(common_debug_level_current,"Remote took longer that 300 seconds to send file.");
  send_to_modem(modem_port_no,"quit");   /* TEMP: 300-second timeout needs to be changed so that xfers longer than that detect the beginning of the xfer. */
  send_to_modem(modem_port_no,CR_string);
  return(2);
  }
send_to_modem(modem_port_no,"quit");       /* We got the file; detach from site. */
send_to_modem(modem_port_no,CR_string);
wait(1);
send_to_modem(modem_port_no,CTRL_Y_string);
if (waitfor(modem_port_no,vax_prompt_string,3,common_debug_level_current))
  {
	common_debug_message(common_debug_level_current,"!Didn't get VMS prompt after trying to quit FTP.");
	return(3);
  }
wait(1);
trash_modem_output(modem_port_no,common_debug_level_current);
send_to_modem(modem_port_no,"sz ");       /* Now get the file from the Vax to here. */
send_to_modem(modem_port_no,transfer_filename);
send_to_modem(modem_port_no,CR_string);
errcode = spawnlp(P_WAIT,"P:\GSZ.EXE","port ",modem_port_string," rz","-rr",NULL);
if (errcode == -1)
  {
  printf("\n?Problem calling GSZ.EXE to receive file (error -1).\n");
  printf(" errno variable set by spawn command: %d\n",errno);
  return(3);
  }
if (errcode)
  {
  printf("\n?Problem calling GSZ.EXE to receive file\n");
  printf(" Error code %d\n",errcode);
  return(3);
  }
wait(3);
trash_modem_output(modem_port_no,common_debug_level_current);
/* Everything went ok; the file is in the current area.   */
/*  Create a message to requestor with the file attached. */
strcpy(temp_string,";");
strcat(temp_string,CTRL_A_string);
strcat(temp_string,"FLAGS KFS");
strcat(temp_string,CR_string);
strcpy(temp_string_2,file_storage_directory_spec);
strcat(temp_string_2,transfer_filename);
if ( fidonet_send_message("FIDO_FTP -- the Internet accesser",
                          incoming_header.fromUserName,
                          temp_string,
                          temp_string_2,
                          netmail_directory_spec,
                          incoming_header.destNode_loworder,
                          incoming_header.destNode_highorder,
                          incoming_header.origNode_loworder,
                          incoming_header.origNode_highorder,
                          incoming_header.origNet_loworder,
                          incoming_header.origNet_highorder,
                          incoming_header.destNet_loworder,
                          incoming_header.destNet_highorder,
                          common_debug_level_current) )
  exit(ERRORLEVEL_FATAL);
return(0);
}

int ftp_get_directory_from_site(char *directory_spec_to_get,int the_mode)
{                 /* the_mode is 0 for DIR list, 1 for ls -R list. */
/* 0 if ok (file is attached), 1 if bad site, 2 if bad directory spec, 3 if program error, 4 if couldn't even log on, 5 if links down.  */
FILE *directory_listing_file; /* Where we capture the directory listing to. */
int unique_number=0,temp_char,result_code;
char LF_char=10,CR_char=13,previous_char=0,one_char,temp_string[100];
if (!logged_onto_vax_flag)    /* Are we already logged onto the Vax?    */
  if (vax_logon())  /* Problem logging onto the Vax?                    */
    return(4);      /*   Don't do anything or mark message as received. */
result_code = ftp_attach_to_site();
if (result_code==2)
  return(5);        /* Indicate that links to site are probably down. */
if (result_code==1)
  return(1);
/* Find an unused directory listing file and use it. */
while (1)   /* Do this until we break out. */
  {
  strcpy(directory_listing_filename,file_storage_directory_spec);
  strcat(directory_listing_filename,"DIR_LIST.");
  itoa(unique_number++,temp_string,10);
  strcat(directory_listing_filename,temp_string);
  directory_listing_file = fopen(directory_listing_filename,"rb");
  if (directory_listing_file == NULL)   /* Found a preexisting file? */
    break;
  fclose(directory_listing_file);     /*  Close and look for next. */
  /* Go back and try the next number, which is already in unique_number. */
  }
common_debug_message_w_no(common_debug_level_current,"Creating listing file DIR_LIST.",unique_number-1);
directory_listing_file = fopen(directory_listing_filename,"wb+");
if (directory_listing_file == NULL)
  {
  printf("?Error opening directory listing file %s\n",directory_listing_filename);
  exit(ERRORLEVEL_CONFIGURATION);
  }
strcpy(temp_string,"SITE=");
strcat(temp_string,the_sitename);
strcat(temp_string,CRLF_string);
fwrite(temp_string,strlen(temp_string),1,directory_listing_file);
strcpy(temp_string,"DIR=");
strcat(temp_string,directory_spec_to_get);
strcat(temp_string,CRLF_string);
strcat(temp_string,CRLF_string);
fwrite(temp_string,strlen(temp_string),1,directory_listing_file);
if (the_mode)
  send_to_modem(modem_port_no,"ls -R");
else
  {
  send_to_modem(modem_port_no,"dir ");
  send_to_modem(modem_port_no,directory_spec_to_get);
  }
send_to_modem(modem_port_no,CR_string);
wait(1);
trace_start("fer complete");  /* Now the listing is starting to spew forth. */
while(!trace_fired("fer complete"))  /* Go until we're done or we break out. */
  {
  temp_char = get_char_from_modem_with_timeout(modem_port_no,30);
  if (temp_char == -1)  /* Did the timeout occur? */
    {
    common_debug_message(common_debug_level_current,"!Timeout while getting directory listing.");
    break;              /*   Yeah, just assume that the listing finished. */
    }
  if (common_debug_level_screen >= common_debug_level_current)
    printf("%c",(char)temp_char);
  trace_process_received_character((char)temp_char);
  one_char = (char)temp_char;
  if ((one_char == LF_char) && (previous_char != CR_char))  /* Add CR before LFs. */
    fwrite(&CR_char,1,1,directory_listing_file);
  fwrite(&one_char,1,1,directory_listing_file);
  previous_char = one_char;
  }
trace_stop("fer complete",common_debug_level_current);
fclose(directory_listing_file);
wait(2);
trash_modem_output(modem_port_no,common_debug_level_current);
send_to_modem(modem_port_no,"quit");  /* We got the listing; detach from site.*/
send_to_modem(modem_port_no,CR_string);
if (waitfor(modem_port_no,vax_prompt_string,3,common_debug_level_current))
  {
	printf("!Didn't get VMS prompt after trying to quit FTP.\n");
  return(3);
  }
wait(2);
trash_modem_output(modem_port_no,common_debug_level_current);
/*  Create a message to requestor with the file attached. */
strcpy(temp_string,";");
strcat(temp_string,CTRL_A_string);
strcat(temp_string,"FLAGS KFS");
strcat(temp_string,CR_string);
if ( fidonet_send_message("FIDO_FTP -- the Internet accesser",
                          incoming_header.fromUserName,
                          temp_string,
                          directory_listing_filename,
                          netmail_directory_spec,
                          incoming_header.destNode_loworder,
                          incoming_header.destNode_highorder,
                          incoming_header.origNode_loworder,
                          incoming_header.origNode_highorder,
                          incoming_header.origNet_loworder,
                          incoming_header.origNet_highorder,
                          incoming_header.destNet_loworder,
                          incoming_header.destNet_highorder,
													common_debug_level_current) )
	exit(ERRORLEVEL_FATAL);
return(0);
}

int read_character_from_message()  /* Returns character or -1 for EOF. */
{                                  /*  Also return EOF if NULL found.  */
char input_char;
int result;
read_character:
result = fread(&input_char,1,1,incoming_file);
if (!result)            /* End of file?  Return EOF.           */
	return(-1);
if (input_char == 00)   /* End of message found; return EOF.   */
	return(-1);
if (input_char == 10)   /* Skip linefeeds in the message body. */
	goto read_character;
return(input_char);
}

int parse_message_line()  /* Sets global variables parsed_keyword and    */
{                         /* and parsed_value.  Returns non-zero if EOF. */
int parsed_keyword_pointer=0,parsed_value_pointer=0,char_from_file,
    parsed_message_line_pointer=0;

common_debug_message(common_debug_level_current,"parse_message_line()");
parsed_keyword[0] = 0;  /* Initialize to null strings. */
parsed_value[0]   = 0;
parsed_message_line[0] = 0;
char_from_file = read_character_from_message(); /* Read 1st char from message.*/
if (char_from_file == -1)   /* EOF? */
	return(1);
while (1)     /* Process/read characters until we break out. */
	{
	if (char_from_file == 13)
		{
		parsed_keyword[parsed_keyword_pointer] = 0;
		parsed_message_line[parsed_message_line_pointer] = 0;
		return(0);
		}
	parsed_keyword[parsed_keyword_pointer++] = char_from_file;
	parsed_message_line[parsed_message_line_pointer++] = char_from_file;
	if (parsed_keyword_pointer == sizeof(parsed_keyword))
		return(0);   /* Before it overflows! */
	if (parsed_message_line_pointer == sizeof(parsed_message_line))
		return(0);
	char_from_file = read_character_from_message();
	if (char_from_file == -1)
		{
		parsed_keyword[parsed_keyword_pointer] = 0;  /* Terminate string. */
		parsed_message_line[parsed_message_line_pointer] = 0;
		return(0);
		}
	if (char_from_file == '=')
		{
		parsed_keyword[parsed_keyword_pointer] = 0;
		parsed_message_line[parsed_message_line_pointer++] = '=';
		break;
		}              /* Go and read characters after '=' sign. */
	/* Go and read next character of keyword. */
	}
char_from_file = read_character_from_message();
if (char_from_file == -1)
	{
	parsed_message_line[parsed_message_line_pointer] = 0;
	return(0);
	}
while (1)
	{
	if (char_from_file == 13)
		{
		parsed_value[parsed_value_pointer] = 0;
		parsed_message_line[parsed_message_line_pointer] = 0;
		break;
		}
	parsed_value[parsed_value_pointer++] = char_from_file;
	parsed_message_line[parsed_message_line_pointer++] = char_from_file;
	if (parsed_value_pointer == sizeof(parsed_value))
		break;  /* Prevent overflow! */
	if (parsed_message_line_pointer == sizeof(parsed_message_line))
		break;
	char_from_file = read_character_from_message();
	if (char_from_file == -1)
		{
		parsed_value[parsed_value_pointer] = 0;
		parsed_message_line[parsed_message_line_pointer] = 0;
		break;
		}
	}
return(0);  /* This line is never reached but eliminates warning message. */
}

int process_keyword_dir(char *parsed_value,int the_mode) /* Returns non-zero if message should not be marked as received. */
{                /* the_mode is 0 for DIR command, 1 for ls -R command. */
int error_code;
error_code = ftp_get_directory_from_site(parsed_value,the_mode);
if (error_code==5)  /* Link down, probably. */
  {
  add_to_message_body_file("  Couldn't access site; links are probably down.  Skipping this line.");
  return(0);
  }
if (error_code==4)  /* Couldn't log onto vax or access sites. */
  return(1);   /* So message doesn't get marked as received. */
if (error_code==3)
  {
	if (add_to_message_body_file("  FIDO_FTP error; please notify sysop so he can check his logs and fix things."))
		{
		printf("?Error adding to message body file.\n");
		exit(ERRORLEVEL_FATAL);
		}
	common_debug_message(common_debug_level_current,"Just wrote  FIDO_FTP error; please notify...  to message_body_file.");
	return(0);
  }
if (error_code==2)
  {
  strcpy(temp_string,"  The directory listing for ");
  strcat(temp_string,parsed_value);
	strcat(temp_string,CRLF_string);
  strcat(temp_string,"  could not be retrieved.");
	if (add_to_message_body_file(temp_string))
		{
		printf("?Error adding to message body file.\n");
		exit(ERRORLEVEL_FATAL);
		}
	return(0);
  }
if (error_code==1)
  {
  strcpy(temp_string,"  The sitename ");
  strcat(temp_string,the_sitename);
  strcat(temp_string,CRLF_string);
  strcat(temp_string,"  could not be accessed.  Is it valid?");
	if (add_to_message_body_file(temp_string))
		{
		printf("?Error adding to message body file.\n");
		exit(ERRORLEVEL_FATAL);
		}
	return(0);
  }
strcpy(temp_string,"  You requested a directory listing for ");
strcat(temp_string,parsed_value);
if (!strlen(parsed_value))  /* Was parsed_value null?  Add _something_! */
  strcat(temp_string,"the root directory");
if (add_to_message_body_file(temp_string))
  {
  printf("?Error adding to message body file: You requested a directory...\n");
  exit(ERRORLEVEL_FATAL);
  }
strcpy(temp_string,"  and it has been file-attached to you as ");
strcat(temp_string,directory_listing_filename);
if (add_to_message_body_file(temp_string))
	{
    printf("?Error adding to message body file:  and it has been...\n");
	exit(ERRORLEVEL_FATAL);
	}
return(0);
}

void process_keyword_password(char *parsed_value)
{
strcpy(ftp_password,parsed_value);
if (add_to_message_body_file("  Noted."))
	{
	printf("?Error adding to message body file.\n");
	exit(ERRORLEVEL_FATAL);
	}
return;
}

void process_keyword_username(char *parsed_value)
{
strcpy(ftp_username,parsed_value);
if (add_to_message_body_file("  Noted."))
	{
	printf("?Error adding to message body file.\n");
	exit(ERRORLEVEL_FATAL);
	}
return;
}

void process_keyword_site(char *parsed_value)
{
strcpy(the_sitename,parsed_value);
if (add_to_message_body_file("  Noted."))
	{
	printf("?Error adding to message body file.\n");
	exit(ERRORLEVEL_FATAL);
	}
return;
}

process_keyword_get(char *parsed_value)
{
int error_code;
error_code = ftp_get_file_from_site(parsed_value);
if (error_code==5)  /* Link down, probably. */
	{
	add_to_message_body_file("  Couldn't access site; links are probably down.  Skipping this line.");
	return(0);
	}
if (error_code==4)  /* Couldn't log onto vax or access sites. */
	return(1);   /* Not marking message as received -- we'll try next time. */
if (error_code==3)
	{
	if (add_to_message_body_file("  FIDO_FTP error; please notify sysop so he can check his logs and fix things."))
		{
		printf("?Error adding to message body file.\n");
		exit(ERRORLEVEL_FATAL);
		}
	return(0);
	}
if (error_code==2)
	{
	strcpy(temp_string,"  The file ");
	strcat(temp_string,parsed_value);
	strcat(temp_string,CRLF_string);
	strcat(temp_string,"  could not be retrieved.");
	if (add_to_message_body_file(temp_string))
		{
		printf("?Error adding to message body file.\n");
		exit(ERRORLEVEL_FATAL);
		}
	return(0);
	}
if (error_code==1)
  {
  strcpy(temp_string,"  The sitename ");
  strcat(temp_string,the_sitename);
  strcat(temp_string,CRLF_string);
  strcat(temp_string,"  could not be accessed.  Is it valid?");
	if (add_to_message_body_file(temp_string))
		{
		printf("?Error adding to message body file.\n");
		exit(ERRORLEVEL_FATAL);
		}
	return(0);
  }
strcpy(temp_string,"  You requested the file ");
strcat(temp_string,parsed_value);
if (add_to_message_body_file(temp_string))
	{
    printf("?Error adding to message body file: You request file...\n");
	exit(ERRORLEVEL_FATAL);
	}
strcpy(temp_string,"  and it has been file-attached to you as ");
strcat(temp_string,transfer_filename);
if (add_to_message_body_file(temp_string))
	{
    printf("?Error adding to message body file:  and it has been...\n");
	exit(ERRORLEVEL_FATAL);
	}
return(0);
}

void process_this_message()
{
int error_code=0;  /* Set to 1 if we couldn't log on while processing this         */
		   /*   message or had to save it for later for some other reason. */
char file_to_attach[64]="";
common_debug_message_w_no(common_debug_level_current,"Processing message ",message_number);
decode_attribute_word((incoming_header.AttributeWord_highorder*256)+incoming_header.AttributeWord_loworder);
if (flag_recd)  /* This message already received? */
  return;
if (init_message_body_file())  /* Where we echo incoming and write reply lines to.*/
	{
	printf("?Error initializing message body file\n");
	exit(ERRORLEVEL_FATAL);
	}
if (add_to_message_body_file("--- This is a reply to a message you sent to FIDO_FTP ---"))
	{
	printf("?Error adding to message body file.\n");
	exit(ERRORLEVEL_FATAL);
	}
strcpy(ftp_username,"anonymous");     /* Initialize to defaults. */
strcpy(ftp_password,"xxxxxxx@panam2.panam.edu");  /* The default value. */
while (!parse_message_line())    /* Read lines until EOF. */
  {
  if (!parsed_message_line[0])   /* Blank line? */
    continue;                    /*   Skip it!  */
  if (parsed_message_line[0] != 1)  /* Don't echo kludge lines to requester. */
    {
    if (add_to_message_body_file(parsed_message_line))
      {
			printf("?Error adding to message body file.\n");
      exit(ERRORLEVEL_FATAL);
      }
    }
	if  (!strcmp(parsed_keyword,"SITE"))
    process_keyword_site(parsed_value);
	else
  if (!strcmp(parsed_keyword,"GET"))
    error_code = process_keyword_get(parsed_value);
  else
  if (!strcmp(parsed_keyword,"DIR"))
    error_code = process_keyword_dir(parsed_value,0);
  else
  if (!strcmp(parsed_keyword,"DIRALL"))
    error_code = process_keyword_dir(parsed_value,1);
  else
  if (!strcmp(parsed_keyword,"PASSWORD"))
    process_keyword_password(parsed_value);
  else
  if (!strcmp(parsed_keyword,"USERNAME"))
    process_keyword_username(parsed_value);
  else
  if (parsed_keyword[0] == 1)
		common_debug_message(common_debug_level_current,"Skipping kludge line.");
	else
		{
		if (add_to_message_body_file("  Attached is a help file for FIDO_FTP."))
			{
			printf("?Error adding to message body file.\n");
			exit(ERRORLEVEL_FATAL);
			}
		strcpy(file_to_attach,help_file_name);
    }
  /* Done processing this message line; ready for the next one. */
  if (error_code)   /* Trouble logging on?  Quit and don't mark message as received. */
    break;
  }
if (error_code)  /* Avoid marking this message as received. */
  return;
if ( fidonet_send_message("FIDO_FTP -- the Internet accesser",  /* Send the reply.*/
                          incoming_header.fromUserName,
                          message_body_filename,
                          file_to_attach,
                          netmail_directory_spec,
                          incoming_header.destNode_loworder,
                          incoming_header.destNode_highorder,
                          incoming_header.origNode_loworder,
                          incoming_header.origNode_highorder,
                          incoming_header.origNet_loworder,
                          incoming_header.origNet_highorder,
                          incoming_header.destNet_loworder,
                          incoming_header.destNet_highorder,
                          common_debug_level_current) )
  exit(ERRORLEVEL_FATAL);
common_debug_message(common_debug_level_current,"Setting incoming message header's status to 'rcvd'.");
incoming_header.AttributeWord_loworder |= 4;  /* Mark this message received. */
if (fseek(incoming_file,(long)0,SEEK_SET))
  {
  printf("?Unable to fseek to beginning of incoming message file to mark as 'rcvd'\n");
  exit(ERRORLEVEL_FATAL);
  }
result = fwrite(&incoming_header,1,sizeof(struct message_header_type),incoming_file);
if (!result)
  {
  printf("?Error rewriting message header of incoming file\n");
  exit(ERRORLEVEL_FATAL);
  }
common_debug_message(common_debug_level_current,"End of process_this_message()");
}

/*--------------------------- The Code -------------------------------------*/
int main(int argc, char *argv[])
{
printf("----Begin program execution....");
if (argc != 2)
  {
	printf("?Illegal number of arguments; command line syntax:  \n");
	printf("    FIDO_FTP FIDO_FTP.CFG                           \n");
	printf("  where FIDO_FTP.CFG is the spec of the config file.\n");
  return(ERRORLEVEL_BAD_PARAMETER);
  }
strcpy(config_file_name,argv[1]);
config_file = fopen(config_file_name,"rt");
if (config_file == NULL)
  {
  printf("?Can't open config file %s\n",config_file_name);
  exit(ERRORLEVEL_BAD_PARAMETER);
  }
fgets(help_file_name,sizeof(help_file_name),config_file);
help_file_name[strlen(help_file_name)-1] = 0;  /* Cut off LF. */
fgets(sitelist_file_name,sizeof(sitelist_file_name),config_file);
sitelist_file_name[strlen(sitelist_file_name)-1] = 0;
fgets(netmail_directory_spec,sizeof(netmail_directory_spec),config_file);
netmail_directory_spec[strlen(netmail_directory_spec)-1] = 0;
if (netmail_directory_spec[strlen(netmail_directory_spec)-1] != '\\')  {
  netmail_directory_spec[strlen(netmail_directory_spec)+1] = 0;
  netmail_directory_spec[strlen(netmail_directory_spec)]   = '\\';     }
fgets(file_storage_directory_spec,sizeof(file_storage_directory_spec),config_file);
file_storage_directory_spec[strlen(file_storage_directory_spec)-1] = 0;
if (file_storage_directory_spec[strlen(file_storage_directory_spec)-1] != '\\')  {
  file_storage_directory_spec[strlen(file_storage_directory_spec)+1] = 0;
  file_storage_directory_spec[strlen(file_storage_directory_spec)]   = '\\';     }
fgets(vax_phone_number,sizeof(vax_phone_number),config_file);
vax_phone_number[strlen(vax_phone_number)-1] = 0;
fgets(vax_account_name,sizeof(vax_account_name),config_file);
vax_account_name[strlen(vax_account_name)-1] = 0;
fgets(vax_account_password,sizeof(vax_account_password),config_file);
vax_account_password[strlen(vax_account_password)-1] = 0;
fgets(modem_port_string,sizeof(modem_port_string),config_file);
modem_port_string[strlen(modem_port_string)-1] = 0;
fgets(temp_string,sizeof(temp_string),config_file);
temp_string[strlen(temp_string)-1] = 0;
common_debug_level_screen = atoi(temp_string);
fgets(temp_string,sizeof(temp_string),config_file);
temp_string[strlen(temp_string)-1] = 0;
if (common_set_log_filename(temp_string))
  {
  printf("?Bad log file name: %s\n",temp_string);
  exit(ERRORLEVEL_FATAL);
  }
fgets(temp_string,sizeof(temp_string),config_file);
temp_string[strlen(temp_string)-1] = 0;
common_debug_level_logfile = atoi(temp_string);
fclose(config_file);

if (common_debug_level_screen)
	{
	printf("Help file spec:         %s\n",help_file_name);
	printf("Site list file spec:    %s\n",sitelist_file_name);
	printf("Netmail directory spec: %s\n",netmail_directory_spec);
	printf("File storage directory: %s\n",file_storage_directory_spec);
	printf("Vax phone number:       %s\n",vax_phone_number);
	printf("Vax account name:       %s\n",vax_account_name);
	printf("Vax account password:   %s\n",vax_account_password);
	printf("Modem comm port number: %s\n",modem_port_string);
	printf("Debug level (screen):   %d\n",common_debug_level_screen);
    printf("Log file name:          %s\n",common_log_filename);
    printf("Debug level (logfile):  %d\n",common_debug_level_logfile);
	}
modem_port_no = atoi(modem_port_string) - 1;  /* Convert and subtract 1. */

CR_string[0] = 13;  /* We'll use this for stuff. */
CR_string[1] = 0;
CRLF_string[0] = 13;
CRLF_string[1] = 10;
CRLF_string[2] = 0;
CTRL_A_string[0] = 1;
CTRL_A_string[1] = 0;
CTRL_U_string[0] = 21;
CTRL_U_string[1] = 0;
CTRL_Y_string[0] = 25;
CTRL_Y_string[1] = 0;
DOUBLE_QUOTE_string[0] = '"';
DOUBLE_QUOTE_string[1] = 0;

comm_port_open();

flag_file = fopen(flag_file_name,"wb");   /* Leave behind blank flag file. */
fclose(flag_file);

message_number = 0;        /* Start looking for messages addressed to us. */
while (1)   /* Do this until we break out. */
  {
  if (message_number++ == MAX_MSGS_TO_SCAN)    /* Check, then increment. */
	break;
  strcpy(incoming_file_name,netmail_directory_spec);
  itoa(message_number,temp_string,10);
  strcat(incoming_file_name,temp_string);
  strcat(incoming_file_name,message_file_suffix);
  incoming_file = fopen(incoming_file_name,"rb+");
  if (incoming_file != NULL)   /* Found a message file?     */
	{
    fread(&incoming_header,sizeof(struct message_header_type),1,incoming_file);
    temp_string[0] = 0;
    strncat(temp_string,incoming_header.toUserName,sizeof(incoming_header.toUserName));
    strupr(temp_string);
    result = memcmp(temp_string,"FIDO_FTP",9);
    if (!result)
      process_this_message(); /* We found a message addressed to us. */
    fclose(incoming_file);
    common_debug_message(common_debug_level_current,"Now looking for next message file.");
    }
  if (kbhit())   /* Was a key hit?  If so, then quit processing messages. */
    {
    getch();          /* Zap character from buffer.                 */
    while (kbhit())   /* Trash extra characters in buffer (if any). */
      getch();
    break;
    }
  }
if (logged_onto_vax_flag)
  {
  common_debug_message(common_debug_level_current,"Logging off of the VAX.");
  vax_logoff();
  }
common_debug_message(common_debug_level_current,"Deleting flag file.");
unlink(flag_file_name);
common_debug_message(common_debug_level_current,"Closing comm port.");
comm_port_close();
common_debug_message(common_debug_level_current,"FIDO_FTP will exit 1 second from now.");
wait(1);
return(ERRORLEVEL_SUCCESS);
}


