/******************************************************************************/
/*                                                                            */
/*  GNU Phantom.Homed 1.00                                                    */
/*  06/26/2000                                                                */
/*  Copyright (C) 1999, 2000 by Joe Thielen <jthielen@accesstoledo.com>       */
/*                                                                            */
/*  This program 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 of the License, or (at your    */
/*  option) any later version.                                                */
/*                                                                            */
/******************************************************************************/

#include <iostream.h>
#include <stdio.h>
#include <unistd.h>
#include <asm/io.h>
#include <sys/io.h>
#include <string>
#include <fstream.h>
#include <time.h>
#include <ctype.h>

#define VERSION2 "1.00"
#define BASEPORT 0x378
#define BASEPORT2 0x379
#define Phantom_Out "Phantom.Home.Out"
#define Phantom_In "Phantom.Home.In"
#define Phantom_PID "Phantom.PID"
#define Phantom_Devices "Phantom.Devices"
#define Phantom_Groups "Phantom.Groups"
#define Phantom_Log "Phantom.Homed.Log"

void parse_devices(ifstream& file_devices, bool &D1_S, bool &D2_S, bool &D3_S, bool &D4_S, bool &D5_S, bool &D6_S, bool &D7_S, bool &D8_S, string &D1_A, string &D2_A, string &D3_A, string &D4_A, string &D5_A, string &D6_A, string &D7_A, string &D8_A, bool verbose, bool &ef, bool logging, ofstream& log_file, int &returnstatus)
{
	/* PARSE_DEVICES:                                                  */
	/* This function takes the options in the Phantom.Devices file and */
	/* sucks it into data we can use.  This function, along with       */
	/* parse_groups are necessary, and need to be error checked, in    */
	/* order to make the most of this package.   As well as make it    */
	/* easier to use!                                                  */


	if (verbose==true) {cout << "Reading Phantom.Devices file...";};
	if (logging==true)
	{
		log_file.open(Phantom_Log, ios::app);
		log_file << "Reading Phantom.Devices file...";
		log_file.close();
	}

	const char nwln = '\n';
	char x;
	int i;
	string q1, q2, q3;

	/* Open up the Phantom.Devices file */
	file_devices.open (Phantom_Devices);

	if (file_devices.fail())
	{

		if (verbose==true)
		{
			cout << "None." << endl;
		}

		cout << "FATAL ERROR: Phantom.Homed requires the config file Phantom.Devices!" << endl;

		if (logging==true)
		{
			log_file.open(Phantom_Log, ios::app);
			log_file << "None." << endl;
			log_file << "FATAL ERROR: Phantom.Homed requires the config file Phantom.Devices!" << endl;
			log_file.close();
		}

		ef = true;
		returnstatus=2;
	}
	
	/* Start the process by getting the first char */
	file_devices.get (x);
	while (!file_devices.eof () && ef == false)
	{
		i = 1;
		q1 = ""; q2 = ""; q3 = ""; 
		while (x != nwln)
		{
			if (x != ':')
			{
				if (i == 1) {q1 = q1 + x;}
				if (i == 2) {q2 = q2 + x;}
				if (i == 3) {q3 = q3 + x;}
				file_devices.get (x);
			}
			else
			{
				i++;
				file_devices.get (x);
			}
		}
		file_devices.get (x);

		if (q1 == "DEVICE1")
		{
			if (q2 == "Enabled")
			{
				D1_S = true;
				D1_A = q3;
			}
			else
			{
				D1_S = false;
			}
		}
		if (q1 == "DEVICE2")
		{
			if (q2 == "Enabled")
			{
				D2_S = true;
				D2_A = q3;
			}
			else
			{
				D2_S = false;
			}
		}
		if (q1 == "DEVICE3")
		{
			if (q2 == "Enabled")
			{
				D3_S = true;
				D3_A = q3;
			}
			else
			{
				D3_S = false;
			}
		}
		if (q1 == "DEVICE4")
		{
			if (q2 == "Enabled")
			{
				D4_S = true;
				D4_A = q3;
			}
			else
			{
				D4_S = false;
			}
		}
		if (q1 == "DEVICE5")
		{
			if (q2 == "Enabled")
			{
				D5_S = true;
				D5_A = q3;
			}
			else
			{
				D5_S = false;
			}
		}
		if (q1 == "DEVICE6")
		{
			if (q2 == "Enabled")
			{
				D6_S = true;
				D6_A = q3;
			}
			else
			{
				D6_S = false;
			}
		}
		if (q1 == "DEVICE7")
		{
			if (q2 == "Enabled")
			{
				D7_S = true;
				D7_A = q3;
			}
			else
			{
				D7_S = false;
			}
		}
		if (q1 == "DEVICE8")
		{
			if (q2 == "Enabled")
			{
				D8_S = true;
				D8_A = q3;
			}
			else
			{
				D8_S = false;
			}
		}
		
	}

	if (ef == false) 
	{
		/* Close the Phantom.Devices file */
		file_devices.close ();
		if (verbose==true) {cout << "Done!" << endl;};
		if (logging==true)
		{
			log_file.open(Phantom_Log, ios::app);
			log_file << "Done!" << endl;
			log_file.close();
		}
	}
}

void parse_groups(ifstream& file_groups, string &G1_A, string &G2_A, string &G3_A, string &G4_A, string &G1_D, string &G2_D, string &G3_D, string &G4_D, bool verbose, bool logging, ofstream& log_file)
{
	/* PARSE_GROUPS:                                                    */
	/* This function reads the Phantom.Groups alias file.  Groups are   */
	/* just aliases for user defined groups of devices.  For example,   */
	/* let's say you have two lights that you want to retain individual */
	/* control over, yet you want some easy way to turn both of them on */
	/* or off at the same time.  Then you can create a group called     */
	/* 'lights' or something, and do it that easily!                    */

	if (verbose==true) {cout << "Reading Phantom.Groups file...";}
	if (logging==true)
	{
		log_file.open(Phantom_Log, ios::app);
		log_file << "Reading Phantom.Groups file...";
		log_file.close();
	}

	const char nwln = '\n';
	char x;
	int i;
	string q1, q2, q3, q4;
	bool ef;

	ef = false;

	/* If someones got a screwy Phantom.Groups file, */
	/* better put some checks in...                  */
	/* In other words, guilty until proven innocent! */
	G1_A = "N/A";
	G2_A = "N/A";
	G3_A = "N/A";
	G4_A = "N/A";

	/* Open up the Phantom.Groups file */
	file_groups.open (Phantom_Groups);

	if (file_groups.fail())
	{
		if (verbose==true) {cout << "None." << endl;};
		if (logging==true)
		{
			log_file.open(Phantom_Log, ios::app);
			log_file << "None." << endl;
			log_file.close();
		}
		ef=true;
	}

	/* Start the process by getting the first char */
	file_groups.get (x);
	while (!file_groups.eof () && ef == false)
	{
		i = 1;
		q1 = ""; q2 = ""; q3 = ""; q4 = "";

		while (x != nwln)
		{
			if (x != ':')
			{
				if (i == 1) {q1 = q1 + x;}
				if (i == 2) {q2 = q2 + x;}
				if (i == 3) {q3 = q3 + x;}
				if (i == 4) {q4 = q4 + x;}
				file_groups.get (x);
			}
			else
			{
				i++;
				file_groups.get (x);
			}
		}
		file_groups.get (x);

		if (q1 == "GROUP1")
		{
			if (q2 == "Enabled")
			{
				G1_A = q3;
				G1_D = q4;
			}
			else
			{
				G1_A = "N/A";
				G1_D = "N/A";
			}
		}
		if (q1 == "GROUP2")
		{
			if (q2 == "Enabled")
			{
				G2_A = q3;
				G2_D = q4;
			}
			else
			{
				G2_A = "N/A";
				G2_D = "N/A";
			}
		}
		if (q1 == "GROUP3")
		{
			if (q2 == "Enabled")
			{
				G3_A = q3;
				G3_D = q4;
			}
			else
			{
				G3_A = "N/A";
				G3_D = "N/A";
			}
		}
		if (q1 == "GROUP4")
		{
			if (q2 == "Enabled")
			{
				G4_A = q3;
				G4_D = q4;
			}
			else
			{
				G4_A = "N/A";
				G4_D = "N/A";
			}
		}
	}
	
	if (ef == false)
	{
		/* Close out the Phantom.Groups file */
		file_groups.close();
		if (verbose==true) {cout << "Done!" << endl;}
		if (logging==true)
		{
			log_file.open(Phantom_Log, ios::app);
			log_file << "Done!" << endl;
			log_file.close();
		}
	}
}

void read_file(ifstream& Phantom_Out_i, bool &D1, bool &D2, bool &D3, bool &D4, bool &D5, bool &D6, bool &D7, bool &D8, string G1_D, string G2_D, string G3_D, string G4_D, bool D1_S, bool D2_S, bool D3_S, bool D4_S, bool D5_S, bool D6_S, bool D7_S, bool D8_S, bool &ef, bool &nogo, int &oldtime, ofstream& Phantom_In_o, bool &alights_s, bool alights)
{
	char x,y;

	string o;

	int counter;

	time_t curtime;	
	struct tm *loctime;

	curtime = time (NULL);
	loctime = localtime (&curtime);

	/* Default nogo to true */
	nogo=true;

	/* If we just cycle at the max speed allowed, then we'll be writing */
	/* to the file so fast that sometimes no one else can!  So let's get */
	/* a small delay in here... */
	if (curtime != oldtime)
	{
		/* Open the Phantom.Home.Out file... */
		Phantom_Out_i.open (Phantom_Out);

		if (!Phantom_Out_i.fail())
		{

			/* Get one character from the file */
			Phantom_Out_i.get (x);

			/* Close the Phantom.Home.Out file... */
			Phantom_Out_i.close ();

			/* Now we don't want to read this file again with the */
        		/* same character, so we've got to delete it          */
			remove (Phantom_Out);

			/* Is it a DEVICE? */
			if (x=='0')
			{
				if (D1==true) {o="1";} else {o="0";};
				if (D2==true) {o=o+"1";} else {o=o+"0";};
				if (D3==true) {o=o+"1";} else {o=o+"0";};
				if (D4==true) {o=o+"1";} else {o=o+"0";};
				if (D5==true) {o=o+"1";} else {o=o+"0";};
				if (D6==true) {o=o+"1";} else {o=o+"0";};
				if (D7==true) {o=o+"1";} else {o=o+"0";};
				if (D8==true) {o=o+"1";} else {o=o+"0";};

				Phantom_In_o.open(Phantom_In);
				Phantom_In_o << o;
				Phantom_In_o.close();
			}
			if (x=='1') {if (D1==true) {D1=false;} else {D1=true;};nogo=false;};
			if (x=='2') {if (D2==true) {D2=false;} else {D2=true;};nogo=false;};
			if (x=='3') {if (D3==true) {D3=false;} else {D3=true;};nogo=false;};
			if (x=='4') {if (D4==true) {D4=false;} else {D4=true;};nogo=false;};
			if (x=='5') {if (D5==true) {D5=false;} else {D5=true;};nogo=false;};
			if (x=='6') {if (D6==true) {D6=false;} else {D6=true;};nogo=false;};
			if (x=='7') {if (D7==true) {D7=false;} else {D7=true;};nogo=false;};
			if (x=='8') {if (D8==true) {D8=false;} else {D8=true;};nogo=false;};
			if (x=='9') {ef=true;nogo=true;};

			/* Is it ALL (ON) ? */
			if (tolower(x)=='p')
			{
				D1=true;
				D2=true;
				D3=true;
				D4=true;
				D5=true;
				D6=true;
				D7=true;
				D8=true;
				nogo=false;
			}

			/* Is it ALL (OFF) ? */
			if (tolower(x)=='q')
			{
				D1=false;
				D2=false;
				D3=false;
				D4=false;
				D5=false;
				D6=false;
				D7=false;
				D8=false;
				nogo=false;
			}

			/* Is it GROUP 1 (ON) ? */
			if (tolower(x)=='h' && G1_D != "N/A")
			{
				for (counter=0;counter < G1_D.length(); counter ++)
				{
					y=G1_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=true;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=true;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=true;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=true;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=true;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=true;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=true;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=true;nogo=false;};};
				}
			}
			/* Is it GROUP 1 (OFF) ? */
			if (tolower(x)=='l' && G1_D != "N/A")
			{
				for (counter=0;counter < G1_D.length(); counter ++)
				{
					y=G1_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=false;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=false;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=false;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=false;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=false;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=false;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=false;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=false;nogo=false;};};
				}
			}

			/* Is it GROUP 2 (ON) ? */
			if (tolower(x)=='i' && G2_D != "N/A")
			{
				for (counter=0;counter < G2_D.length(); counter ++)
				{
					y=G2_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=true;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=true;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=true;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=true;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=true;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=true;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=true;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=true;nogo=false;};};
				}
			}
			/* Is it GROUP 2 (OFF) ? */
			if (tolower(x)=='m' && G2_D != "N/A")
			{
				for (counter=0;counter < G2_D.length(); counter ++)
				{
					y=G2_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=false;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=false;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=false;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=false;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=false;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=false;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=false;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=false;nogo=false;};};
				}
			}

			/* Is it GROUP 3 (ON) ? */
			if (tolower(x)=='j' && G3_D != "N/A")
			{
				for (counter=0;counter < G3_D.length(); counter ++)
				{
					y=G3_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=true;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=true;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=true;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=true;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=true;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=true;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=true;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=true;nogo=false;};};
				}
			}
			/* Is it GROUP 3 (OFF) ? */
			if (tolower(x)=='n' && G3_D != "N/A")
			{
				for (counter=0;counter < G3_D.length(); counter ++)
				{
					y=G3_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=false;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=false;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=false;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=false;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=false;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=false;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=false;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=false;nogo=false;};};
				}
			}

			/* Is it GROUP 4 (ON) ? */
			if (tolower(x)=='k' && G4_D != "N/A")
			{
				for (counter=0;counter < G4_D.length(); counter ++)
				{
					y=G4_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=true;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=true;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=true;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=true;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=true;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=true;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=true;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=true;nogo=false;};};
				}
			}
			/* Is it GROUP 4 (OFF) ? */
			if (tolower(x)=='o' && G4_D != "N/A")
			{
				for (counter=0;counter < G4_D.length(); counter ++) {
					y=G4_D.at (counter);
					if (y=='1') {if (D1_S==true) {D1=false;nogo=false;};};
					if (y=='2') {if (D2_S==true) {D2=false;nogo=false;};};
					if (y=='3') {if (D3_S==true) {D3=false;nogo=false;};};
					if (y=='4') {if (D4_S==true) {D4=false;nogo=false;};};
					if (y=='5') {if (D5_S==true) {D5=false;nogo=false;};};
					if (y=='6') {if (D6_S==true) {D6=false;nogo=false;};};
					if (y=='7') {if (D7_S==true) {D7=false;nogo=false;};};
					if (y=='8') {if (D8_S==true) {D8=false;nogo=false;};};
				}
			}

			if (tolower(x)=='r' && alights == true) {alights_s = true;}
			if (tolower(x)=='s' && alights == true) {alights_s = false;}
			

		}
	}

	oldtime=curtime;
}

void Phantom_Output(bool D1, bool D2, bool D3, bool D4, bool D5, bool D6, bool D7, bool D8, bool nogo, bool verbose, bool logging, ofstream& log_file)
{
	/* PHANTOM_OUTPUT: */

	/* total is the value to be shot through the parallel port */
	int total;

	/* TIME */
	time_t curtime;
	struct tm *loctime;

	/* Now, we don't need to write to the port EVERY CYCLE.  We just */
	/* want to write to it when there is a CHANGE.  So if there is a */
	/* change (as indicated by the nogo var), then "Make it so!"     */
	if (nogo==false)
	{

		total=0;

		if (D1 == true) {total=total+1;};
		if (D2 == true) {total=total+2;};
		if (D3 == true) {total=total+4;};
		if (D4 == true) {total=total+8;};
		if (D5 == true) {total=total+16;};
		if (D6 == true) {total=total+32;};
		if (D7 == true) {total=total+64;};
		if (D8 == true) {total=total+128;};

		/* Now shoot the total through the parallel port! */
		outb(total, BASEPORT);

		if (verbose==true) 
		{
			cout << D1 << D2 << D3 << D4 << D5 << D6 << D7 << D8 << endl;
		}
		if (logging==true) 
		{
			curtime=time(NULL);
			loctime=localtime(&curtime);

			log_file.open(Phantom_Log, ios::app);
			log_file << D1 << D2 << D3 << D4 << D5 << D6 << D7 << D8 << " " << asctime(loctime);
			log_file.close();
		}
	}
}

void Door_Check(bool &D1, bool &D2, bool &D3, bool &D4, bool &D5, bool &D6, bool &D7, bool &D8, bool &nogo, int &oldtime2, bool alights, bool alights_s)
{
	/* Only if the autolights feature is enabled via the command-line */
	/* AND it is currently enabled shall we do this...                */
	if (alights == true & alights_s == true)
	{

	/* GET_INPUT:                                                       */
	/* The routine that reads the status of the printer port.  However, */
	/* the number returned by the 'INB(X)' statement is an integer      */
	/* between 0-255.  We have five inputs, so that intenger has to be  */
	/* broken down into the five IZx (Input Zone x) variables,          */
	/* which signal if the state of the pin is high or low (on or off)  */

	/* TIME */
	time_t curtime;
	curtime=time(NULL);

	int X;
	int IZ1, IZ2, IZ3, IZ4, IZ5;
	IZ1 = 0;
	IZ2 = 0;
	IZ3 = 0;
	IZ4 = 0;
	IZ5 = 0;

	/* Get the input from the parallel port located at BASEPORT */
	X=inb(BASEPORT2);
	
	/* Break 'X' down into the five Input Zones (IZx) */
	switch (X)
	{
		case 135: IZ1=0;IZ2=0;IZ3=0;IZ4=0;IZ5=0;break;
		case 143: IZ1=1;IZ2=0;IZ3=0;IZ4=0;IZ5=0;break;
		case 151: IZ1=0;IZ2=1;IZ3=0;IZ4=0;IZ5=0;break;
		case 167: IZ1=0;IZ2=0;IZ3=1;IZ4=0;IZ5=0;break;
		case 199: IZ1=0;IZ2=0;IZ3=0;IZ4=1;IZ5=0;break;
		case 7  : IZ1=0;IZ2=0;IZ3=0;IZ4=0;IZ5=1;break;
		case 159: IZ1=1;IZ2=1;IZ3=0;IZ4=0;IZ5=0;break;
		case 175: IZ1=1;IZ2=0;IZ3=1;IZ4=0;IZ5=0;break;
		case 207: IZ1=1;IZ2=0;IZ3=0;IZ4=1;IZ5=0;break;
		case 15 : IZ1=1;IZ2=0;IZ3=0;IZ4=0;IZ5=1;break;
		case 183: IZ1=0;IZ2=1;IZ3=1;IZ4=0;IZ5=0;break;
		case 215: IZ1=0;IZ2=1;IZ3=0;IZ4=1;IZ5=0;break;
		case 23 : IZ1=0;IZ2=1;IZ3=0;IZ4=0;IZ5=1;break;
		case 231: IZ1=0;IZ2=0;IZ3=1;IZ4=1;IZ5=0;break;
		case 39 : IZ1=0;IZ2=0;IZ3=1;IZ4=0;IZ5=1;break;
		case 71 : IZ1=0;IZ2=0;IZ3=0;IZ4=1;IZ5=1;break;
		case 127: IZ1=1;IZ2=1;IZ3=1;IZ4=1;IZ5=1;break;
		case 191: IZ1=1;IZ2=1;IZ3=1;IZ4=0;IZ5=0;break;
		case 63 : IZ1=1;IZ2=1;IZ3=1;IZ4=0;IZ5=1;break;
		case 247: IZ1=0;IZ2=1;IZ3=1;IZ4=1;IZ5=0;break;
		case 103: IZ1=0;IZ2=0;IZ3=1;IZ4=1;IZ5=1;break;
		case 255: IZ1=1;IZ2=1;IZ3=1;IZ4=1;IZ5=0;break;
		case 119: IZ1=0;IZ2=1;IZ3=1;IZ4=1;IZ5=1;break;
		case 95 : IZ1=1;IZ2=1;IZ3=0;IZ4=1;IZ5=1;break;
		case 111: IZ1=1;IZ2=0;IZ3=1;IZ4=1;IZ5=1;break;
		case 31 : IZ1=1;IZ2=1;IZ3=0;IZ4=0;IZ5=1;break;
		case 55 : IZ1=0;IZ2=1;IZ3=1;IZ4=0;IZ5=1;break;
		case 87 : IZ1=0;IZ2=1;IZ3=0;IZ4=1;IZ5=1;break;
		case 47 : IZ1=1;IZ2=0;IZ3=1;IZ4=0;IZ5=1;break;
		case 79 : IZ1=1;IZ2=0;IZ3=0;IZ4=1;IZ5=1;break;
		case 239: IZ1=1;IZ2=0;IZ3=1;IZ4=1;IZ5=0;break;
		case 223: IZ1=1;IZ2=1;IZ3=0;IZ4=1;IZ5=0;break;
	}

	if (IZ5 == true)
	{
		/* go ahead and turn light on */
		/* & make a note of the time  */
		if (D4 == false)
		{
			D4 = true;
			nogo = false;
			oldtime2 = curtime;
		}
	}
	else
	{
		/* See if oldtime2 = 0, if so, do nothing. */
		/* Otherwise, see if time - oldtime2 > 180 */
		/* seconds, then turn the light off!       */
		if (oldtime2 != 0)
		{
			if (curtime - oldtime2 > 180)
			{
				D4 = false;
				nogo = false;
				oldtime2 = 0;
			}
		}
	}

	}
	else
	{
		oldtime2=0;
	}
}


void main(int argc, char *argv[])
{
	/* Declare the 8 Device variables */
	bool D1, D2, D3, D4, D5, D6, D7, D8;
	/* Declare the 8 Device status variables */
	bool D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S;
	/* Declare the 8 Device Alieas Variables */
	string D1_A, D2_A, D3_A, D4_A, D5_A, D6_A, D7_A, D8_A;
	/* Declare 4 Group Aliases */
	string G1_A, G2_A, G3_A, G4_A;
	/* Declare 4 Group Devices */
	string G1_D, G2_D, G3_D, G4_D;
	/* Declare Phantom_Out_i as input file stream */
	ifstream Phantom_Out_i;
	/* Declare Phantom_In_o as an output file stream */
	ofstream Phantom_In_o;
	/* Declare file_groups as an input file stream */
	ifstream file_groups;
	/* Declare file_devices as an input file stream */
	ifstream file_devices;
	/* Declare file_pid as an output file stream */
	ofstream file_pid;
	/* Declare file_log as an output file stream */
	ofstream log_file;
	/* Declare ef as boolean exit flag */
	bool ef;
	/* Declare nogo as boolean */
	bool nogo;
	/* oldtime is used for a time delay (oldtime2 for lights) */
	int oldtime, oldtime2;
	/* declare verbose as a bool, used for '-v' option */
	bool verbose;
	/* declare logging as a bool, used for '-l' option */
	bool logging;
	/* counter is a counter used in for loops */
	int counter;
	/* temp is a temporary storage string */
	string temp;
	/* temp2 is a temporary storage integer */
	int temp2;
	/* declare homedir as a char */
	char homedir[128] = "";
	/* declare tempchar as a char */
	char tempchar;
	/* declare returnstatus as int */
	int returnstatus;
	/* declare alights as a bool, used for '-a' option */
	bool alights, alights_s;

	/* TIME */
	time_t curtime;
	struct tm *loctime;

	/* Initialize Variables */
	D1=0;D2=0;D3=0;D4=0;D5=0;D6=0;D7=0;D8=0;
	ef=false;
	nogo=true;
	verbose=false;
	logging=false;
	oldtime2 = 0;
	alights=false;
	alights_s=false;

	/* ---------- PARSE COMMAND LINE --------- */
	for (counter = 1; counter < argc; counter++)
	{
		temp=argv[counter];

		if (temp=="--version")
		{
			cout << "GNU Phantom.Homed " << VERSION2 << endl;
			cout << "Copyright (C) 1999, 2000 by Joe Thielen <jthielen@accesstoledo.com>" << endl;
			cout << "GNU Phantom.Homed comes with NO WARRANTY," << endl;
			cout << "to the extent permitted by law." << endl;
			cout << "You may redistribute copies of GNU Phantom.Homed" << endl;
			cout << "under the terms of the GNU General Public License" << endl;
			cout << "For more information about these matters," << endl;
			cout << "see the file named COPYING." << endl << endl;
			ef=true;
			returnstatus = 0;
		}

		if (temp=="--help")
		{
			cout << "GNU Phantom.Homed " << VERSION2 << endl;
			cout << "Copyright (C) 1999, 2000 by Joe Thielen <jthielen@accesstoledo.com>" << endl << endl;
			cout << "Arguments: " << endl;	
			cout << "--help        To get this list" << endl;
			cout << "--version     To get the version" << endl;
			cout << "-v            To enable verbose mode" << endl;
			cout << "-l            To enable logging mode" << endl;
			cout << "-a            To enable auto lights mode" << endl;
			cout << endl;
			ef=true;
			returnstatus = 0;
		}

		if (temp == "-v") {verbose=true;};

		if (temp == "-l") {logging=true;};

		if (temp == "-a") {alights=true;};
	}
	/* ---------- PARSE COMMAND LINE --------- */
	
	/* Determine command line arguments */
	for (counter = 1; counter < argc ; counter++)
	{
		temp=argv[counter];
	}

	if (logging==true && ef==false) 
	{
		curtime=time(NULL);
		loctime=localtime(&curtime);

		log_file.open(Phantom_Log, ios::app);
		log_file << "GNU Phantom.Homed Start " << asctime(loctime);
		log_file.close();
	}

	if (ef == false)
	{
		/* Read Phantom.Devices file */
		parse_devices(file_devices, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A, D7_A, D8_A, verbose, ef, logging, log_file, returnstatus);
	}

	if (ef == false)
	{
		/* Output process ID (PID) to Phantom.Home.PID */
		file_pid.open(Phantom_PID);
		temp2=(getpid());
		file_pid << temp2;
		file_pid.close ();

		/* Read Phantom.Groups file */
		parse_groups(file_groups, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, verbose, logging, log_file);


	/* Open the parallel port for access */
	ioperm(BASEPORT,3,1);

	}

	while (ef==false)
	{
		usleep(500);

		/* FIRST, check Phantom.Home.Out file */
		read_file(Phantom_Out_i, D1, D2, D3, D4, D5, D6, D7, D8, G1_D, G2_D, G3_D, G4_D, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, ef, nogo, oldtime, Phantom_In_o, alights_s, alights);

		/* THEN, check the status of the door (if enabled) */
		Door_Check(D1, D2, D3, D4, D5, D6, D7, D8, nogo, oldtime2, alights, alights_s);
	
		/* LAST, output to the parallel port */
		Phantom_Output(D1, D2, D3, D4, D5, D6, D7, D8, nogo, verbose, logging, log_file);

	}

	/* remove PID & Out file upon exit */
	remove(Phantom_PID);
	remove(Phantom_Out);

	/* Close the parallel port for access */
	ioperm(BASEPORT,3,0);

	if (logging==true) 
	{
		curtime=time(NULL);
		loctime=localtime(&curtime);

		log_file.open(Phantom_Log, ios::app);
		log_file << "GNU Phantom.Homed Stop " << asctime(loctime);
		log_file.close();
	}

	return returnstatus;
}
