/* Copyright (C) 2004 Per Johansson
	
	This file is part of netGo.

    netGo 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.

    netGo 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 netGo; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <qprocess.h>
#include <qstringlist.h>
#include <qtimer.h>
#include <qmessagebox.h>
#include <qregexp.h>
#include <qstring.h>
#include <qtextbrowser.h>
#include <qpushbutton.h>

#include "process.h"
#include "profile.h"
#include "settings.h"

// Default constructor for class Process.
Process::Process(QTextBrowser *procBrowser, QPushButton *okButton)
{
	// Save the textbrowser in a variable that all the member-methods can access.
	browser = procBrowser;
	
	// Save the ok-button in variables that all the member-methods can acces.
	okBut = okButton;
	
	// Set the dhcp-error variable to 0.
	DHCP_ERROR = 0;
	
	// Bash escape sequences for coloured text.
	blue = "\e[0;34m";
	BLUE = "\e[1;34m";
	green = "\e[0;32m";
	GREEN = "\e[1;32m";
	red = "\e[0;31m";
	RED = "\e[1;31m";
	magenta = "\e[0;35m";
	MAGENTA = "\e[1;35m";
	cyan = "\e[0;36m";
	CYAN = "\e[1;36m";
	normal = "\e[0m";
	NORMAL = "\e[1m";
}


/*------------------------------------------
      Functions for exiting a process.
------------------------------------------*/

// Function for a safe exit.
void Process::cleanUp()
{
	// Mark that no process is running at the moment.
	CURRENT_PROC = NONE;

	// Enable the Ok-button again to show that we're done.
	okBut->setEnabled(1);
	okBut->setFocus();
	
	// Show the command line user that we're done.
	qWarning("\n" + NORMAL + "- Done!" + normal);
	
	// Emit a signal to show that the processes are finished.
	emit procsFinished();
}

// Function that is called when user press the Cancel-button.
// It terminates the current network process.
void Process::terminateProc()
{
	// Find out which process that were running when the user clicked Cancel,
	// and try to terminate that one.
	switch (CURRENT_PROC) {
		case NONE:
			// Do nothing, this means that there was no process running.
			qWarning("No process were running..");
			break;
		case IFACEDOWN:
			ifaceDownProc->tryTerminate();
			QTimer::singleShot( 1000, ifaceDownProc, SLOT( kill() ) );
			qWarning("Killed interfaceDownProc..");
			break;
		case KILLDHCP:
			killDhcpProc->tryTerminate();
			QTimer::singleShot( 1000, killDhcpProc, SLOT( kill() ) );	
			qWarning("Killed killDhcpProc...");
			break;
		case DHCP:
			dhcpProc->tryTerminate();
			QTimer::singleShot( 1000, dhcpProc, SLOT( kill() ) );	
			qWarning("Killed dhcpProc..");
			break;
		case FETCHIP:
			fetchIpProc->tryTerminate();
			QTimer::singleShot( 1000, fetchIpProc, SLOT( kill() ) );
			qWarning("Killed fetchIpProc..");
			break;
		case STATICIP:
			ipProc->tryTerminate();
			QTimer::singleShot( 1000, ipProc, SLOT( kill() ) );	
			qWarning("Killed ipProc..");
			break;
		case NETMASK:
			netmaskProc->tryTerminate();
			QTimer::singleShot( 1000, netmaskProc, SLOT( kill() ) );
			qWarning("Killed netmaskProc..");	
			break;
		case GW:
			gwProc->tryTerminate();
			QTimer::singleShot( 1000, gwProc, SLOT( kill() ) );
			qWarning("Killed gwProc..");	
			break;
		case MODE:
			modeProc->tryTerminate();
			QTimer::singleShot( 1000, modeProc, SLOT( kill() ) );
			qWarning("Killed modeProc..");
			break;
		case ESSID:
			essidProc->tryTerminate();
			QTimer::singleShot( 1000, essidProc, SLOT( kill() ) );
			qWarning("Killed essidProc..");
			break;
		case KEY:
			keyProc->tryTerminate();
			QTimer::singleShot( 1000, keyProc, SLOT( kill() ) );
			qWarning("Killed keyProc..");
			break;
		};
}


/*------------------------------------------
      Functions for executing a profile
------------------------------------------*/

// Function for executing a profile.
void Process::runProfile(const QString &name)
{
	// Clear the textbrowser.
	browser->clear();
		
	// Disable the ok-button during the execution of the profile.
	okBut->setEnabled(0);
	
	// Clear this variable to show that no process is running at the moment.
	CURRENT_PROC = NONE;
	
	// Loop through the vector and find the profile we want to execute.
	for (current=0; current<Profile::profiles.size(); current++) {
		if (Profile::profiles.at(current).name == name) // Check if the current profile is matching the arg.
			break;
	}
	
	// Save each command in a QStringList.
	ifaceDown << Settings::IFCONFIG_PATH << Profile::profiles.at(current).iface << "down";
	killDhcp << Settings::DHCP_CLIENT_PATH << "-k" << Profile::profiles.at(current).iface;
	setDhcp << Settings::DHCP_CLIENT_PATH << Profile::profiles.at(current).iface;
	fetchIp << Settings::IFCONFIG_PATH << Profile::profiles.at(current).iface;
	setIp << Settings::IFCONFIG_PATH << Profile::profiles.at(current).iface << Profile::profiles.at(current).ip;
	setNetmask << Settings::IFCONFIG_PATH << Profile::profiles.at(current).iface << "netmask" << Profile::profiles.at(current).netmask;
    setGw << Settings::ROUTE_PATH << "add" << "default" << "gw" << Profile::profiles.at(current).gw;
	setScript << "sh" << Profile::profiles.at(current).scriptPath;
	setMode << Settings::IWCONFIG_PATH << Profile::profiles.at(current).iface << "mode" << Profile::profiles.at(current).mode;
	setEssid << Settings::IWCONFIG_PATH << Profile::profiles.at(current).iface << "essid" << Profile::profiles.at(current).essid;
	if (Profile::profiles.at(current).keyType == "ascii")
		setKey << Settings::IWCONFIG_PATH << Profile::profiles.at(current).iface << "key" << "s:" + Profile::profiles.at(current).key; 
	else if (Profile::profiles.at(current).keyType == "hex")
		setKey << Settings::IWCONFIG_PATH << Profile::profiles.at(current).iface << "key" <<  Profile::profiles.at(current).key; 		
	else 
		setKey << Settings::IWCONFIG_PATH << Profile::profiles.at(current).iface << "key" << "off"; 		
	
	// Start with setting the wireless mode.
	startModeProc();
}

// Function that sets the wireless mode (ie. managed, ad-hoc).
void Process::startModeProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).mode == "None") {
		startEssidProc();
		return;
	}

	// Print that we're about to set the wireless-mode.
	browser->setText(browser->text() + "* Setting wireless mode: <b>" + Profile::profiles.at(current).mode + "</b><br>");
	qWarning(green + "* Setting wireless mode: " + GREEN + Profile::profiles.at(current).mode + normal);
	
	// Create and execute the process that sets the wireless-mode.
    modeProc = new QProcess(0, "modeProc");
	modeProc->setArguments(setMode); // Pass the arguments to the process.
    
	// Start the process.
	if (!modeProc->start()) {
    	qWarning(red + "- Error: " + Settings::IWCONFIG_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>Error: " + Settings::IWCONFIG_PATH + ": command not found.</font><br>");
		startEssidProc();
		return;
	}
	
	// Mark the current process.
	CURRENT_PROC = MODE;
	
	// Continue with the nameservers when the gateway has been set.
	connect(modeProc, SIGNAL(processExited()), this, SLOT(startEssidProc()) );

	// Establish connections between the process and its error-output.
	connect(modeProc, SIGNAL(readyReadStderr()), this, SLOT(modeErr()) );
}

// Function that sets the essid (for wireless networks).
void Process::startEssidProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).essid.isEmpty()) {
		startKeyProc();
		return;
	}

	// Print that we're about to set the essid.
	browser->setText(browser->text() + "* Setting essid: <b>" + Profile::profiles.at(current).essid + "</b><br>");
	qWarning(green + "* Setting essid: " + GREEN + Profile::profiles.at(current).essid + normal);
	
	// Create and execute the process that sets the essid.
    essidProc = new QProcess(0, "essidProc");
	essidProc->setArguments(setEssid); // Pass the arguments to the process.
    
	// Start the process.
	if (!essidProc->start()) {
    	qWarning(red + "- Error: " + Settings::IWCONFIG_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>Error: " + Settings::IWCONFIG_PATH + ": command not found.</font><br>");
		startKeyProc();
		return;
	}
	// Mark the current process.
	CURRENT_PROC = ESSID;
	
	// Continue with the nameservers when the gateway has been set.
	connect(essidProc, SIGNAL(processExited()), this, SLOT(startKeyProc()) );

	// Establish connections between the process and its error-output.
	connect(essidProc, SIGNAL(readyReadStderr()), this, SLOT(essidErr()) );
}

// Function that sets the encryption (for wireless networks).
void Process::startKeyProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).key.isEmpty()) {
		startIfaceDown();
		return;
	}
	
	QString output;
	if (Profile::profiles.at(current).keyType == "ascii")
		output = "* Setting key (ascii): ";	
	else if (Profile::profiles.at(current).keyType == "hex") 
		output = "* Setting key (hex): ";
	
	// Print that we're about to set the encrypyion-key.
	browser->setText(browser->text() + output + "<b>" + Profile::profiles.at(current).key + "</b><br>");
	qWarning(green + output + GREEN + Profile::profiles.at(current).key + normal);
	
	// Create and execute the process that sets the encryption key.
    keyProc = new QProcess(0, "keyProc");
	keyProc->setArguments(setKey); // Pass the arguments to the process.
    
	// Start the process.
	if (!keyProc->start()) {
    	qWarning(red + "- Error: " + Settings::IWCONFIG_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>Error: " + Settings::IWCONFIG_PATH + ": command not found.</font><br>");
		startIfaceDown();
		return;
	}
		
	// Mark the current process.
	CURRENT_PROC = KEY;
	
	// Continue with bringing down interfaces when the gateway has been set.
	connect(keyProc, SIGNAL(processExited()), this, SLOT(startIfaceDown()) );

	// Establish connections between the process and its error-output.
	connect(keyProc, SIGNAL(readyReadStderr()), this, SLOT(keyErr()) );
}


// Function that brings down an interface.
void Process::startIfaceDown()
{	
	// Check if we should skip this task (which is bringing down the interface).
	if (Profile::profiles.at(current).iface == "None" || Profile::profiles.at(current).ip.isEmpty() ) {
		startGwProc();
		return;
	}
		
	// Print that we're about to bring down the interface.
	browser->setText(browser->text() + "* Bringing down interface <b>" + Profile::profiles.at(current).iface + "</b><br>");
	qWarning(green + "* Bringing down interface " + GREEN + Profile::profiles.at(current).iface + normal);
		
	// Create the process that brings down the interface.
	ifaceDownProc = new QProcess(0, "ifaceDownProc");
	ifaceDownProc->setArguments(ifaceDown); // Pass the arguments to the process.

	// Start the process.
	if (!ifaceDownProc->start() ) { 
		qWarning(red + "- Error: " + Settings::IFCONFIG_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>Error: " + Settings::IFCONFIG_PATH + ": command not found.</font><br>");

		// Check if we should continue with the dhcp process or set a static-ip.
		if (Profile::profiles.at(current).ip == "dhcp") {
			// Check which dhcp client that shall be used.
			if (Settings::DHCP_CLIENT == "dhcpcd") {
				startKillDhcp();
				return;
			}
			else if (Settings::DHCP_CLIENT == "dhclient") {
				startDhcpProc();
				return;
			}
		}
		// Or set a static ip.
		else {
			startIpProc();
			return;
		}
	}
		
	// Mark the current process.
	CURRENT_PROC = IFACEDOWN;
	
	// Check if we should broadcast for an ip-adress or set a static-ip.
	if (Profile::profiles.at(current).ip == "dhcp") {
		// Check which dhcp client that shall be used.
		if (Settings::DHCP_CLIENT == "dhcpcd")
			connect(ifaceDownProc, SIGNAL(processExited()), this, SLOT(startKillDhcp()) );
		else if (Settings::DHCP_CLIENT == "dhclient")
			connect(ifaceDownProc, SIGNAL(processExited()), this, SLOT(startDhcpProc()) );
	}
	else
		connect(ifaceDownProc, SIGNAL(processExited()), this, SLOT(startIpProc()) );
	
	// Establish connections between the process and its error-output.
	connect(ifaceDownProc, SIGNAL(readyReadStderr()), this, SLOT(ifaceDownErr()) );
}

// Function that kills a possible dhcpcd process.
void Process::startKillDhcp()
{	
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).ip.isEmpty() )
		startNetmaskProc();
	
	// Print that we're about to kill  a possible dhcpcd-process.
	browser->setText(browser->text() + "* Killing a possible dhcpcd  process<br>");
	qWarning(green + "* Killing a possible dhcpcd process" + normal);
	
	// Start with creating a process that kills a possible dhcp-process.
	killDhcpProc = new QProcess(0, "killDhcpProc");
	killDhcpProc->setArguments(killDhcp);
	
	// Start the process.
	if (!killDhcpProc->start() ) {
		qWarning(red + "- Error: " + Settings::DHCP_CLIENT_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>" + Settings::DHCP_CLIENT_PATH + ": command not found.</font><br>");
		startDhcpProc();
		return;
	}

	// Mark the current process.
	CURRENT_PROC = KILLDHCP;
	
	// Continue with broadcasting for an ip after we have killed the dhcp-process.	
	connect(killDhcpProc, SIGNAL(processExited()), this, SLOT(startDhcpProc()) );
	
	// Establish connections between the process and its error-output.
	connect(killDhcpProc, SIGNAL(readyReadStderr()), this, SLOT(killDhcpErr()) );
}

// Function that does a dhcp broadcast.
void Process::startDhcpProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Print that we're about to do a dhcp-request.
	browser->setText(browser->text() + "* Requesting DHCP ip for <b> " + Profile::profiles.at(current).iface + "</b>...<br>");
	qWarning(green + "* Requesting DHCP ip for " + GREEN + Profile::profiles.at(current).iface + normal);
	
	// Create the process that broadcasts for ip.
	dhcpProc = new QProcess(0, "dhcpProc");	
	dhcpProc->setArguments(setDhcp); // Pass the arguments to the process.
	
	// Start the process.
	if (!dhcpProc->start()) {
		qWarning(red + "- Error: " + Settings::DHCP_CLIENT_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + " <font color=red>" + Settings::DHCP_CLIENT_PATH + ": command not found.</font><br>");
		DHCP_ERROR = 1;
		startScriptProc();
		return;
	}
		
	// Mark the current process.
	CURRENT_PROC = DHCP;
	
	// Continue with different functions depending on dhcp client.
	if (Settings::DHCP_CLIENT == "dhcpcd")
		connect(dhcpProc, SIGNAL(processExited()), this, SLOT(startFetchIpProc()) );
	else if (Settings::DHCP_CLIENT == "dhclient") 
		connect(dhcpProc, SIGNAL(processExited()), this, SLOT(startScriptProc()) );

	// Establish connections between the process and its error-output.
	connect(dhcpProc, SIGNAL(readyReadStderr()), this, SLOT(dhcpErr()) );
}

// Function that parses out the recieved dhcp ip from `ifconfig`.
void Process::startFetchIpProc() 
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// We shall only try to fetch the recieved ip if the dhcp-process was successfull.
	if (DHCP_ERROR == 1) {
		startScriptProc();
		return;
	}
	
	// Create and execute the process that fetches the ip.
	fetchIpProc = new QProcess(0, "fetchIpProc");
	fetchIpProc->setArguments(fetchIp);
	
	// Start the process.
	if (!fetchIpProc->start() ) {
		qWarning(red + "Error: " + Settings::IFCONFIG_PATH + ": command not found." + normal);
		browser->setText(browser->text() + "<font color=red>Error: " + Settings::IFCONFIG_PATH + ": command not found.</font><br>");
		startScriptProc();
		return;
	}
	
	// Mark the current process.
	CURRENT_PROC = FETCHIP;
	
	// Establish a connection to the standard-output (so we can fetch the ip).	
	connect(fetchIpProc, SIGNAL(readyReadStdout()), this, SLOT(readIp()) );
	
	// Execute the script when we've fetched the ip.
	connect(fetchIpProc, SIGNAL(processExited()), this, SLOT(startScriptProc()) );
}

// Function that sets a static ip adress.
void Process::startIpProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).ip.isEmpty() ) {
		startNetmaskProc();
		return;
	}
	
	// Print that we're about to set a static ip.
    browser->setText(browser->text() + "* Assigning ip <b>" + Profile::profiles.at(current).ip + "</b> to <b>" + Profile::profiles.at(current).iface + "</b><br>");
	qWarning(green + "* Assigning ip " + GREEN + Profile::profiles.at(current).ip + green + " to " + GREEN + Profile::profiles.at(current).iface + normal + normal);
	
	// Create and execute the process that shall set a static ip.
	ipProc = new QProcess(0, "ipProc");
	ipProc->setArguments(setIp); // Pass the arguments to the process.
	
	// Start the process.
	if (!ipProc->start()) {
		qWarning(red + "- Error: " + Settings::IFCONFIG_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>Error: " + Settings::IFCONFIG_PATH + ": command not found.</font><br>");
		startNetmaskProc();
		return;
	}

	// Mark the current process.
	CURRENT_PROC = STATICIP;
	
	// When the process is finished, continue with setting the netmask.
	connect(ipProc, SIGNAL(processExited()), this, SLOT(startNetmaskProc()) );

	// Establish connections between the process and its error-output.
	connect(ipProc, SIGNAL(readyReadStderr()), this, SLOT(ipErr()) );
}
	
// Function that sets the netmask.
void Process::startNetmaskProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).netmask.isEmpty() ) {
		startGwProc();
		return;
	}
	
	// Print that we're about to set the netmask.
	browser->setText(browser->text() + "* Setting netmask: <b>" + Profile::profiles.at(current).netmask + "</b><br>");
	qWarning(green + "* Setting netmask: " + GREEN + Profile::profiles.at(current).netmask + normal);
	
	// Create and execute the process that sets the netmask.
	netmaskProc = new QProcess(0, "netmaskProc");
	netmaskProc->setArguments(setNetmask); // Pass the arguments to the process.
	
	// Start the process.
	if (!netmaskProc->start()) {
		qWarning(red + "- Error: " + Settings::IFCONFIG_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>Error: " + Settings::IFCONFIG_PATH + ": command not found.</font><br>");
		startGwProc();
		return;
	}

	// Mark the current process.
	CURRENT_PROC = NETMASK;	
	
	// When the process is finished, continue with setting the gateway.
	connect(netmaskProc, SIGNAL(processExited()), this, SLOT(startGwProc()) );

	// Establish connections between the process and its error-output.
	connect(netmaskProc, SIGNAL(readyReadStderr()), this, SLOT(netmaskErr()) );
}

// Function that sets the gateway.
void Process::startGwProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).gw.isEmpty()) {
		startNsProc();
		return;
	}

	// Print that we're about to set the gateway.
	browser->setText(browser->text() + "* Setting gateway: <b>" + Profile::profiles.at(current).gw + "</b><br>");
	qWarning(green + "* Setting gateway: " + GREEN + Profile::profiles.at(current).gw + normal);
	
	// Create and execute the process that sets the gateway.
    gwProc = new QProcess(0, "gwProc");
	gwProc->setArguments(setGw); // Fetch the profile-name from "row".
    
	// Start the process.
	if (!gwProc->start()) {
		qWarning(red + "- Error: " + Settings::IFCONFIG_PATH + ": command not found!" + normal);
		browser->setText(browser->text() + "<font color=red>Error:" + Settings::ROUTE_PATH + ": command not found.</font><br>");
		startNsProc();
		return;
	}
	
	// Mark the current process.
	CURRENT_PROC = GW;
	
	// Continue with the nameservers when the gateway has been set.
	connect(gwProc, SIGNAL(processExited()), this, SLOT(startNsProc()) );

	// Establish connections between the process and its error-output.
	connect(gwProc, SIGNAL(readyReadStderr()), this, SLOT(gwErr()) );
}

// Function that sets the nameserver(s) and the search domain.
void Process::startNsProc()
{
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).ns1.isEmpty() && Profile::profiles.at(current).ns2.isEmpty() && Profile::profiles.at(current).search.isEmpty()) {
		startScriptProc();
		return;
	}
	
	// Open /etc/resolv.conf
	QFile resolv("/etc/resolv.conf");
	if (!resolv.open(IO_WriteOnly)) {
		qWarning(red + "- Error: Couldn't open /etc/resolv.conf" + normal);
		browser->setText(browser->text() + "<font color=red>Error: Couldn't open /etc/resolv.conf</font><br>");
	}
	else {
		QTextStream write(&resolv);	
	
		// Print what we're doing and write the settings to /etc/resolv.conf
		if (!Profile::profiles.at(current).ns1.isEmpty()) {
			browser->setText(browser->text() + "* Setting nameserver #1: <b>" + Profile::profiles.at(current).ns1 + "</b><br>");
			qWarning(green + "* Setting nameserver #1: " + GREEN + Profile::profiles.at(current).ns1 + normal);
			write << "nameserver " << Profile::profiles.at(current).ns1 << endl;
		}
		if (!Profile::profiles.at(current).ns2.isEmpty()) {
			browser->setText(browser->text() + "* Setting nameserver #2: <b>" + Profile::profiles.at(current).ns2 + "</b><br>");
			qWarning(green + "* Setting nameserver #2: " + GREEN + Profile::profiles.at(current).ns2 + normal);
			write << "nameserver " << Profile::profiles.at(current).ns2 << endl;
		}
		if (!Profile::profiles.at(current).search.isEmpty()) {
			browser->setText(browser->text() + "* Setting search domain: <b>" + Profile::profiles.at(current).search + "</b><br>");
			qWarning(green + "* Setting search domain: " + GREEN + Profile::profiles.at(current).search + normal);
			write << "nameserver " << Profile::profiles.at(current).search << endl;
		}
		resolv.close();
	}
	
	// Continue with executing the script.
	startScriptProc();
}

// Function that executes the specified script.
void Process::startScriptProc()
{	
	// Mark that no process is running.
	CURRENT_PROC = NONE;
	
	// Check if we should skip this task.
	if (Profile::profiles.at(current).script.isEmpty()) {
		cleanUp();
		return;
	}

	// Print that we're about to execute the script.
	browser->setText(browser->text() + "* Executing script: <b>" + Profile::profiles.at(current).script + "</b><br>");
	qWarning(green + "* Executing script: " + GREEN + Profile::profiles.at(current).script + normal);
	
	// Create and execute the process that sets the gateway.
    scriptProc = new QProcess(0, "scriptProc");
	scriptProc->setArguments(setScript); // Fetch the profile-name from "row".
    
	// Start the process.
	if (!scriptProc->start()) {
		qWarning(red + "- Error: command not found." + normal);
		browser->setText(browser->text() + "<font color=red>Error: command not found.</font><br>");
		cleanUp();
		return;
	}
	
	// Mark the current process.
	CURRENT_PROC = SCRIPT;
	
	// Clean up before finishing.
	connect(scriptProc, SIGNAL(processExited()), this, SLOT(cleanUp()) );

	// Establish connections between the process and its error-output.
	connect(scriptProc, SIGNAL(readyReadStderr()), this, SLOT(scriptErr()) );
}


// Function that prints out the recieved dhcp ip.
void Process::readIp()
{
	QString output, ip;
	int first_pos, bcast_pos; 
			 
	// Save the output in a QString (it's the second line of the output we want).
	output = fetchIpProc->readLineStdout();
	output = fetchIpProc->readLineStdout();
	
	// Parse out the ip-adress.
	first_pos = output.find(":", 0);
	bcast_pos = output.find(" ", first_pos);
	ip = output.mid(first_pos+1, bcast_pos-first_pos-1);
	
	// Finally, show the ip that we've recieved.
	browser->setText(browser->text() + "<font color=#52AA00>- Dhcp-ip recieved: <b>" + ip + "</b></font><br>");
	qWarning(cyan + "- Dhcp-ip recieved: " + CYAN + ip + normal);
}


/*------------------------------------------
       Error-report functions.
------------------------------------------*/

// Prints error messages from the interface down process.
void Process::ifaceDownErr()
{
	// Print the error output to the label.
	QString output = ifaceDownProc->readLineStderr();
	browser->setText(browser->text() + "<font color=red>- Error: " + output + "</font><br>");
	qWarning(red + "- Error: " + output + normal);
} 

// Prints error messages from the kill dhcp process.
void Process::killDhcpErr()
{
	// Read the error output.
	QString output = killDhcpProc->readLineStderr();
	
	// If no dhcpcd proc is running, do not show that particular error msg.
	if (output.find("****  " + Settings::DHCP_CLIENT_PATH + ": not running", 0) != -1)
		return;

	// Print the error output to the label.
	browser->setText(browser->text() + "<font color=red>- Error: " + output + "</font><br>");
	qWarning(red + "- Error: " + output + normal);
}	

// Prints error messages from the dhcp process.
void Process::dhcpErr()
{
	// Handle the error messages different depending on dhpc client.
	if (Settings::DHCP_CLIENT == "dhcpcd") {
		
		// Mark that we've got an error.
		DHCP_ERROR = 1;
		
		// Print the error output to the label.
		QString output = dhcpProc->readLineStderr();
		browser->setText(browser->text() + "<font color=red>- Error: " + output + "</font><br>");
		qWarning(red + "- Error: " + output + normal);
	}
	else if (Settings::DHCP_CLIENT == "dhclient") {
		
		// Loop through all the error output from dhclient.
		while (dhcpProc->canReadLineStderr()) {
			
			QRegExp recievedIp("bound to ((.+)) -- renewal in .+ seconds.$");
			QRegExp noDevice("Bind socket to interface: No such device");
			QRegExp noRecieved("No DHCPOFFERS received.");
			QRegExp noPermission("(SIOCSIFADDR: Permission denied|SIOCSIFFLAGS: Permission denied|Open a socket for LPF: Operation not permitted)");
			QRegExp exited("exiting.$");
			
			// Save each line in output.
			QString output = dhcpProc->readLineStderr();
			
			// Check if the device didn't exist.
			if (noDevice.search(output) != -1) {
				browser->setText(browser->text() + "<font color=red>Error: " + Profile::profiles.at(current).iface + ": No such device.</font><br>");
				qWarning(red + "- Error: " + Profile::profiles.at(current).iface + ": No such device." + normal);
				
				// When we got our error msg, terminate the process.
				dhcpProc->tryTerminate();
				QTimer::singleShot( 1000, dhcpProc, SLOT( kill() ) );
			}
			
			// Check if no dhcp ip was recieved.
			if (noRecieved.search(output) != -1) {
				browser->setText(browser->text() + "<font color=red>Error: No ip recieved.</font><br>");
				qWarning(red + "- Error: No ip recieved." + normal);
				
				// When we got our error msg, terminate the process.
				dhcpProc->tryTerminate();
				QTimer::singleShot( 1000, dhcpProc, SLOT( kill() ) );	
			}
			
			// Check if we got "permission denied".
			if (noPermission.search(output) != -1) {
				browser->setText(browser->text() + "<font color=red>Error: Permission denied.</font><br>");
				qWarning(red + "- Error: Permission denied." + normal);
				
				// When we got our error msg, terminate the process.
				dhcpProc->tryTerminate();
				QTimer::singleShot( 1000, dhcpProc, SLOT( kill() ) );	
			}
			
			// Check if something went wrong and dhclient was exited.
			if (exited.search(output) != -1) {
				browser->setText(browser->text() + "<font color=red>Error: dhclient exited.</font><br>");
				qWarning(red + "- Error: dhclient exited." + normal);
				
				// When we got our error msg, terminate the process.
				dhcpProc->tryTerminate();
				QTimer::singleShot( 1000, dhcpProc, SLOT( kill() ) );	
			}
			
			
			// Check if we have recieved any ip.
			if (recievedIp.search(output) != -1) {
				
				// Try to parse out the recieved ip.
				recievedIp.search(output);
				QString ip = recievedIp.cap(1);
				
				// Print out the ip that we recieved.
				browser->setText(browser->text() + "<font color=#52AA00>- Dhcp-ip recieved: <b>" + ip + "</b></font><br>");
				qWarning(cyan + "- Dhcp-ip recieved: " + CYAN + ip + normal);
			} 
		}
	}
} 

// Prints error messages from the static ip process.
void Process::ipErr()
{
	// Print the error output to the label.
	QString output = ipProc->readLineStderr();
	browser->setText(browser->text() + "<font color=red>- Error: " + output + "</font><br>");
	qWarning(red + "- Error: " + output + normal);
} 

// Prints error messages from the netmask process.
void Process::netmaskErr()
{
	// Print the error output to the label.
	QString output = netmaskProc->readLineStderr();
	browser->setText(browser->text() + "<font color=red>- Error: " + output + "</font><br>");
	qWarning(red + "- Error: " + output + normal);
} 

// Prints error messages from the gateway process.
void Process::gwErr()
{
	// Print the error output to the label.
	QString output = gwProc->readLineStderr();
	browser->setText(browser->text() + " <font color=red>- Error: " + output + "</font><br>");
	qWarning(red + "- Error: " + output + normal);
} 

// Prints error messages from the script process.
void Process::scriptErr()
{
	// Print the error output to the label.
	QString output = scriptProc->readLineStderr();
	browser->setText(browser->text() + "<font color=red>- " + output + "</font><br>");
	qWarning(red + "- " + output + normal);
}
 
// Prints error messages from the wireless mode process.
void Process::modeErr()
{
	// Print the error output to the label.
	QString output = modeProc->readLineStderr();
	browser->setText(browser->text() + "<font color=red>- " + output + "</font><br>");
	qWarning(red + "- " + output + normal);
} 

// Prints error messages from the wireless essid process.
void Process::essidErr()
{
	// Print the error output to the label.
	QString output = essidProc->readLineStderr();
	browser->setText(browser->text() + "<font color=red>- " + output + "</font><br>");
	qWarning(red + "- " + output + normal);
} 

// Prints error messages from the wireless key process.
void Process::keyErr()
{
	// Print the error output to the label.
	QString output = keyProc->readLineStderr();
	browser->setText(browser->text() + "<font color=red>- " + output + "</font><br>");
	qWarning(red + "- " + output + normal);
} 
