#!/bin/bash
# ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
# title			:thumbos
# description		:Loads disk images to thumbdrive from the CLI.
# author		:theemahn <theemahn@ultimateedition.info>
# date			:09/09/2014
# version		:1.1.0
# usage			:thumbos --help
# manual		:man thumbos
# notes			:See change-log below for further information.
# ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
# Change-log:	1.0.1:	Initial Internal Beta release
#
#		1.0.2:	Bug fixes
#
#			Erase feature added.
#
#			Test feature added.
#
#			Display ISO and Image info
#
#		1.03	Minor bugfix see comment in code.
#
#			Supress errors if end user does not possess a thumbdrive,
#			exit graciously.
#
#		1.04	Edited erase routine, NTFS set as default.
#
#			Added partition detection function in case user has
#			multiple partitions on the thumbdrive.
#
#			Added initial ©Microsft Windows support & detection
#			routine.
#
#		1.0.5	Adjustment to test function when booting ISO's
#
#			Added cpu core(s) & memory size detection
#			set VM based on detected hardware.
#
#			Added ntfsprogs to dependancy list, direct check on
#			mkfs.ntfs Broken symlink: The symlink to mkfs.ntfs is
#			wrong. A bug report has been filed.
#
#			Added Eyecandy routines borrowed code from repostorm ;)
#
#			Added notifications and sound, ThumbOS now talks to you.
#
#		1.0.6	Bug Fix: Columize function info output in wrong column.
#
#		1.0.7	Add more comments to code, we are here to learn right?
#
#			Fixed scan function if 2 unknowns are found no output.
#
#			Appended detected size MB / GB etc. Calculating disk
#			sizes smartly up to 999 Yottabytes.
#
#		1.0.8	Added fix for 0 thumbdrives detected. Report and exit.
#
#			Added code for X11 detection in test function.
#
#			Wrote Thumbos initial manpages, postscript and pdf
#			manuals.
#
#		1.0.9	Adjusted recommended in control file to include:
#			gnome-session-canberra, libnotify-bin for sound and
#			notifications.
#
#			Adjusted Virtual testing function to fallback to qemu on
#			KVM acceleration failure.
#
#		1.1.0	Added advanced eyecandy functions for CLI.
#			Initiated construction of a GUI (graphical user interface)
#			Fixed rejection of LOCALE if user is not in the USA
#			Updated Help and error systems
# ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

APPNAME="ThumbOS"
PROGNAME="thumbos"
VERSION="1.1.0"
BUILDDATE="09/09/2014"
WEBSITE="os-builder.com"
AUTHOR="TheeMahn"
EMAIL="<"$AUTHOR"@"$WEBSITE">"

# Initiate a few arrays and vars
declare -a USBDRIVE=();
# Vars for obtaining Disk Information can add and remove based on data requested.
# That is just another reason I love arrays.
declare -a ISOINFO=('System id' 'System id' 'Volume id' 'Publisher id' 'Data preparer' 'Volume size');
((blockSize = 4 * 1024 * 1024))
sp="/-\|"
sc=0

# Added in 1.0.7 - Taking a stab at calculating disk sizes smartly up to Yottabyte
# Could easily roll up to a Geopbyte.
# · 1 Bit = Binary Digit
# · 8 Bits = 1 Byte
# · 1024 Bytes = 1 Kilobyte
# · 1024 Kilobytes = 1 Megabyte
# · 1024 Megabytes = 1 Gigabyte
# · 1024 Gigabytes = 1 Terabyte
# · 1024 Terabytes = 1 Petabyte
# · 1024 Petabytes = 1 Exabyte
# · 1024 Exabytes = 1 Zettabyte
# · 1024 Zettabytes = 1 Yottabyte
# · 1024 Yottabytes = 1 Brontobyte
# · 1024 Brontobytes = 1 Geopbyte 	

# See additional code in function DumpArray to see how I did so using the array
# defined below.
declare -a DISKSIZES=('KB' 'MB' 'GB' 'TB' 'PB' 'EB' 'ZB' 'YB')
#declare -i KBS

# Pull info we will use to compare against later
IUSER=${gksudo_USER:-$USER}
IHOME="/home/$IUSER"

# Retrieve number of lines & columns the screen supports.
LINEZ=$(tput lines)
COLUMNZ=$(tput cols)
SPLIT=0

# check to see if notify is installed & if sound is supported.
NOTIFY=$(which notify-send)
SOUND=$(which canberra-gtk-play)

# GUI SUPPORT?
GUI=$(which zenity)

# Declare integer to span eye-candy routine
declare -i RR
RR=0
declare -i TT
TT=0
declare -i CALC
CALC=0

# set colors so errors etc. stand out.
txtblk='\e[0;30m' # Black - Regular
txtred='\e[0;31m' # Red
txtgrn='\e[0;32m' # Green
txtylw='\e[0;33m' # Yellow
txtblu='\e[0;34m' # Blue
txtpur='\e[0;35m' # Purple
txtcyn='\e[0;36m' # Cyan
txtwht='\e[0;37m' # White
bldblk='\e[1;30m' # Black - Bold
bldred='\e[1;31m' # Red
bldgrn='\e[1;32m' # Green
bldylw='\e[1;33m' # Yellow
bldblu='\e[1;34m' # Blue
bldpur='\e[1;35m' # Purple
bldcyn='\e[1;36m' # Cyan
bldwht='\e[1;37m' # White
unkblk='\e[4;30m' # Black - Underline
undred='\e[4;31m' # Red
undgrn='\e[4;32m' # Green
undylw='\e[4;33m' # Yellow
undblu='\e[4;34m' # Blue
undpur='\e[4;35m' # Purple
undcyn='\e[4;36m' # Cyan
undwht='\e[4;37m' # White
bakblk='\e[40m'   # Black - Background
bakred='\e[41m'   # Red
badgrn='\e[42m'   # Green
bakylw='\e[43m'   # Yellow
bakblu='\e[44m'   # Blue
bakpur='\e[45m'   # Purple
bakcyn='\e[46m'   # Cyan
bakwht='\e[47m'   # White
txtrst='\e[0m'    # Text Reset

function Error () {
	echo -en "${bldred}"
	#FullBar
	Center "$1" "--ERROR"
	#echo -en "${bldred}"
	#FullBar
	echo -en "${txtrst}"
}

function VersionDump {
	Center "$APPNAME ($PROGNAME) $VERSION, $BUILDDATE"
	Encapsulate "GNU $PROGNAME home page: <http://$WEBSITE/>."
	Encapsulate "E-mail bug reports to: $EMAIL."
	Encapsulate "Be sure to include the word $PROGNAME somewhere in the Subject: field."
	FullBar
}

# Declare integer for whether a drive is detatchable.
declare -i DETACHABLE

# Not required, but optional, no promting for testing etc. if false.
QEMUINSTALLED=$(which qemu)

# Prerequisite check - mkntfs
MKNTFS=$(which mkntfs)
if ! [ $MKNTFS ]; then
	MKNTFS=$(which mkfs.ntfs)
fi

# Direct linking mkfs.ntfs https://bugs.launchpad.net/ubuntu/+source/ntfs-3g/+bug/1158732
# To fix, I wrote a mini howto: http://askubuntu.com/questions/343847/mkfs-ntfs-is-not-found-through-the-ntfs-3g-package-is-installed
# For now, I work around the bug by directly checking for the app.

if [[ -f /sbin/mkfs.ntfs ]]; then
	MKNTFS='/sbin/mkfs.ntfs'
fi

if ! [ $MKNTFS ]; then
	Error "Error: mkntfs or mkfs.ntfs program not found!" >&2
	exit 1
fi

# Function for outputting to X-11 screen a notification of completion and playing sound.
# The sound file is from the "Optional" ultimate-edition-sound-theme
function Notification () {
	# Is X11 running?
	X=$( pidof X )
	# Does the user have the optional UE Sound scheme installed?
	if [[ -f "/usr/share/sounds/Ultimate Edition Sound Scheme/stereo/itisdone.wav" ]]; then
		WAVE=1
	fi
	# Is the user in an X11 GUI environment and have notification OSD installed?
	if [[ $X && $NOTIFY ]]; then
		a=$(notify-send "$PROGNAME" "$1" -i /usr/share/ultimate_edition/logo.png -t 5000)
	fi
	# Does the user have pre-requisites? If so, break out the Cylon voice.
	if [[ $SOUND && $WAVE ]]; then
		a=$(canberra-gtk-play -i itisdone 2>/dev/null)
	fi
	# Display message in terminal unconditionally
	zenity --title "ThumbOS" --question --text "$1"; echo $?
}

# Usage: Eye Candy "Message"
function EyeCandy() {
	# Verify a message has been sent to this function otherwise do squat.
	# Example: Eye Candy ('Repostorm $REPOVERSION is entering extraction mode.')
	# ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
	# ▒ Repostorm 1.7.7 is entering extraction mode. ▒
	# ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
	STP="$1"
	if [[ $STP ]]; then
		STRLEN=${#STP}
		STRLEN=$(expr $STRLEN + 5)
		GREPPED=$(echo $STP | grep -E '\e')
		if [[ $GREPPED ]]; then
			STRLEN=$(expr $STRLEN - 13)
		fi
		RR=0; while [ $RR -le $STRLEN ]; do echo -n "▒"; RR=RR+1; done; echo;
		echo -e "▒ "$STP" ▒"
		RR=0; while [ $RR -le $STRLEN ]; do echo -n "▒"; RR=RR+1; done; echo;
	fi
}

function Encapsulate() {
	# Verify a message has been sent to this function otherwise do squat.
	# Example: Encapsulate ('Repostorm $REPOVERSION is entering extraction mode.')
	# ▒ Repostorm 1.7.7 is entering extraction mode.                       ▒

	STP="$1"
	if [[ $STP ]]; then
		STRLEN=${#STP}
		STRLEN=$(expr $STRLEN + 3)
		DISTANCE=$(expr $COLUMNZ - $STRLEN)
		GREPPED=$(echo $STP | grep -E '\e')
		if [[ $GREPPED ]]; then
			STRLEN=$(expr $STRLEN - 13)
		fi
		echo -en "▒ "$STP
		RR=0; while [ $RR -lt $DISTANCE ]; do echo -n " "; RR=RR+1; done; echo "▒";
	fi
}

# Draws a bar across the screen based on screen size detected (columnz)
function FullBar() {
	RR=1; while [ $RR -le $COLUMNZ ]; do echo -n "▒"; RR=RR+1; done; echo;
}

# Center data passed to function on screen
function Center () {
	STP=$1
	ERROR=$2
	if [[ $STP ]]; then
		STRLEN=${#STP}
		CENTER=$(expr $STRLEN / 2 )
		#CENTER=CENTER-1
		TCENTER=$(expr $COLUMNZ / 2 )
		#TCENTER=TCENTER-1
		DISTANCE=$(expr $TCENTER - $CENTER)
		DISTANCE=$(expr $DISTANCE - 2)
		if ! [[ $ERROR ]]; then
			echo -en "${txtrst}"
		else
			echo -en "${bldred}"
		fi
		RR=0; while [ $RR -lt $DISTANCE ]; do echo -n "▒"; RR=RR+1; done;
		echo -en "${bldgrn} $STP "
		if ! [[ $ERROR ]]; then
			echo -en "${txtrst}"
		else
			echo -en "${bldred}"
		fi
		TT=0; while [ $TT -lt $DISTANCE ]; do echo -n "▒"; TT=TT+1; done;
		CALC=$(expr $RR + $TT + $STRLEN + 2)
		if [[ $CALC -lt $COLUMNZ ]]; then
			while [ $CALC -lt $COLUMNZ ]; do echo -n "▒"; CALC=CALC+1; done; echo;
		fi
	fi
	echo -en "${txtrst}"
}

function Columnize () {
	#echo $COLUMNZ
	MAINS=$(echo "scale=2; $COLUMNZ-30" | bc)
	MAINS=${MAINS%.*}
	#echo $MAINS
	MAINS=$(expr $MAINS - 2)
	MAINS=$(expr $MAINS / 4)
	#echo $MAINS
	if ! [[ $1 ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-1s %-1s %-20s %-26s %-7s %-1s\n" "▒" "#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE" 
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-1s %-1s %-20s %-26s %-7s %-1s\n" "▒" $1 $2 $3 $4 $5 $6 
	fi
}

# Debugging function to monitor passed arguments.
function CommandLineIntrepreter(){
	echo -e "${bldgrn}Number of switches passed: $#"
	for var in "$@"
	do
		array_counter=$(($array_counter + 1))
		echo "Switch $array_counter: $var"
	done
}


# Virtual machine testing function.
function Virtual {
	if ! [[ $DISPLAY ]]; then
		Error "No X11 session detected.  Exiting."
		exit 0;
	fi
	# Declare a few integer varibles
	declare -i MEMORY
	declare -i DEDICATED
	TEMPO=$(cat /proc/meminfo | grep 'MemTotal'|cut -d ':' -f2 | sed 's/ kB//g')
	MEMORY=$TEMPO
	# See if end user has 3GB or greater memory
	if [[ $MEMORY -ge 3096000 ]]; then
		# If so set maximum the virtual machine can have.
		DEDICATED=2047
	else
		# Limited resources. Use a quarter the end users memory.
		MAINS=$(echo "scale=2; $MEMORY/1000*.25" | bc)
		# dump the decimal, we want a raw integer.
		DEDICATED=${MAINS%.*}
	fi

	# Snatch the number of CPU Core(s) the end user has.
	CORES=$(cat /proc/cpuinfo | grep "processor" | sed '/model/d' | wc -l)

	# Dump data to the end user.
	Encapsulate "$MEMORY memory and $CORES CPU core(s) detected."
	Encapsulate "Utilizing $DEDICATED MB of memory and $CORES CPU Core(s) to full potential."

	# Check for existance of ISO, if so launch VM, enable kvm acceleration.
	if [ -e "$1" ]; then
		FullBar
		Center "Thumbos: Testing ISO $1 in a virtual machine."
		FullBar
		A=$(qemu-system-x86_64 -enable-kvm -m $DEDICATED --boot d menu=on cdrom=$1 2>/dev/null)
		if ! [[ $A ]]; then
			a=$(kvm -m $DEDICATED -smp $CORES -usb -boot d -cdrom $1 -name ThumbOS 2>/dev/null)
		fi
	else
		# Block device?
		GREPEDSWITCH=$(echo $1 | grep "dev")
		if [[ $GREPPEDSWITCH ]]; then
			if [[ -b $1 ]]; then
				FullBar
				Center "Thumbos: Testing Thumbdrive $1 in a virtual machine."
				FullBar
				A=$(qemu-system-x86_64 -enable-kvm -m $DEDICATED --boot d menu=on cdrom=$1 2>/dev/null)
				if ! [[ $A ]]; then
					a=$(kvm -m $DEDICATED -smp $CORES -usb -boot d -cdrom $1 -name ThumbOS 2>/dev/null)
				fi
			else
				# Lost in space !!! ;)
				Error "Error: Invalid option for test"
				Help test $1 -e
				exit 0
			fi
		else
			TD='/dev/'$1
			if [[ -b $TD ]]; then
				FullBar
				Center "Thumbos: Testing Thumbdrive $TD in a virtual machine."
				FullBar
				A=$(qemu-system-x86_64 -enable-kvm -m $DEDICATED --boot d menu=on cdrom=$TD 2>/dev/null)
				if ! [[ $A ]]; then
					a=$(kvm -m $DEDICATED -smp $CORES -usb -boot d -cdrom $TD -name ThumbOS 2>/dev/null)
				fi
			else
				# Lost in space !!! ;)
				Error "Error: Invalid option for test"
				Help test $1 -e -e
				exit 0
			fi
		fi
	fi
	Notification "All operations completed successfully."
}

function DiskImageInfo {
	# Set needed varibles, we do not need to check for existance of $1 we
	# would not be here if it does not exist
	EXTENSION="${1##*.}"
	FILENAME="${1%.*}"
	BOOTABLE=$((file $1 | grep -m1 "bootable") 2>/dev/null)

	# Don't put full trust in utility "file" for ISO's use the right tool
	# for the right job if file failed.
	if [[ $EXTENSION == 'iso' && $BOOTABLE == '' ]]; then
		BOOTABLE=$((isoinfo -i $1 -f -d | grep -m1 "bootable") 2>/dev/null)
	fi

	
	# Set Boot Flag
	if [[ ${BOOTABLE} ]]; then
		BOOTABLE='Yes'
	else
		BOOTABLE='No'
	fi

	# Come here my pretty ;)
	Center "File: $1"
	# ISO Image? Dump info defined in Array. Makes it simple to add remove info.
	printf '%-15s %s\n' \
	"Image File:" "$1"
	array_counter=1
	for number in ${ISOINFO[@]}
		do
			TITLEINFO=${ISOINFO[$array_counter]}
			GREPINFO=${ISOINFO[$array_counter]}
			DISPLAYINFO=$((isoinfo -d -i $1 | grep -m1 "$GREPINFO" | cut -d: -f2 | sed -e 's/^[ \t]*//') 2>/dev/null)
			if [[ $DISPLAYINFO && $TITLEINFO ]]; then
				printf '%-15s %s\n' \
				"$TITLEINFO:" "$DISPLAYINFO"
			fi
			array_counter=$(($array_counter + 1))
		done

	# Dump info on boot info as detected, we may need some work here,
	# lots of different types of iso's and image files
	printf '%-15s %s\n' \
	"Bootable:" "$BOOTABLE"

	# Thusly inform end user.
	if ! [[ $BOOTABLE ]]; then
		Center "Note: This image most likely will not boot. Proceeding."
	fi
	WINISO=$((isoinfo -d -i $1 | grep -i "win\|microsoft") 2>/dev/null)
	LINUX=$((isoinfo -d -i $1 | grep -i "LINUX") 2>/dev/null)
	APPLE=$((isoinfo -d -i $1 | grep -i "APPLE") 2>/dev/null)
	# Drop additional info if acclible
	if [[ $BOOTABLE && $WINISO ]]; then
		Center "This is a ©Microsoft Windows bootable ISO and will be treated as such."
	fi
	if [[ $BOOTABLE && $LINUX ]]; then
		Center "This is a bootable Linux based operating system and will be treated as such."
	fi
	if [[ $BOOTABLE && $APPLE ]]; then
		Center "This is a bootable Apple/ MAC based operating system and will be treated as such."
	fi
}

# Some eyecandy?
function spin() {

	printf "\b${sp:sc++:1}"
	((sc==${#sp})) && sc=0
}

function endspin() {

	printf "\r%s\n" "$@"
}

function DumpArray () {

	# Yank on Devkit to retrieve availible USBDrives, we will process the data later
	# 1.0.3 fix for 0 thumbdrives dump to /dev/null to avoid output of errors.
	# Open a subshell & parse values.
	NUSBDRIVES=$((ls -l /dev/disk/by-id/*usb* | sed 's/^.*\///g' | sed 's/[0-9]*//g' | uniq | wc -l) 2>/dev/null)
	USBDRIVE=$((ls -l /dev/disk/by-id/*usb* | sed 's/^.*\///g' | sed 's/[0-9]*//g' | uniq) 2>/dev/null)
	# if user has at least one USB drive dump array to screen.
	if [[ $NUSBDRIVES ]]; then
		Encapsulate "Number of USB drives detected: $NUSBDRIVES"
		#Fix for 1.0.8, zero thumbdrives report error.
		if [[ $NUSBDRIVES -lt 1 ]]; then
			Error "Error: No thumbdrives detected."
			exit 0;
		fi
		Columnize
		# Old method, left for educational purposes.
		# printf '%-1s %-1s %-15s %-25s %-10s %s\n' \
		# "#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		FullBar
		echo -e -n "${bldgrn}${txtrst}"
		array_counter=1
		# Stack out a database if you will of detected USB Drives. We will strip out
		# Non hackers as we roll.  No, I do not want my 1TB external showing up as
		# as a thumbdrive.
		for number in ${USBDRIVE[@]}
		do
			TESTVALUE=${USBDRIVE[$array_counter]}
			REMOVABLE='2'
			REMOVABLE=$(lsblk | grep -m1 $number | cut -d ':' -f2 | cut -d" " -f3)
			
			DETACHABLE=$(udisks --show-info /dev/sdh | grep 'detachable' | cut -d ':' -f2)
			
				# Removable is for debugging at this stage of development.
				# Bust out udisks we need raw data on the device(s) in question.
				VENDOR=$(udisks --show-info /dev/$number | grep 'vendor' | cut -d":" -f2 | sed 's/ //g')
				MODEL=$(udisks --show-info /dev/$number | grep 'model' | cut -d":" -f2 | sed 's/ //g')
				if [[ $VENDOR == "" ]]; then
					VENDOR=$MODEL
				fi

				# Still no Vendor?
				if ! [[ $VENDOR ]]; then
					VENDOR='UNKNOWN'
				fi
				BYTES=$(udisks --show-info /dev/$number 2>&1 | grep -m1 'size:' | cut -d":" -f2 | sed 's/ //g')
				LABEL=$(udisks --show-info /dev/$number | grep 'label:' | cut -d ":" -f2 |  sed -e 's/^[ \t]*//')
	
				if [[ $LABEL == "" ]]; then
					LABEL=$(ls -l /dev/disk/by-label/ | grep $number | cut -d ":" -f2 | cut -d " " -f2 | sed 's/\\x20/ /g' 2> /dev/null)
				fi
	
				if ! [[ $LABEL ]]; then
					LABEL="UNKNOWN"
				fi
	
				TYPE=$(udisks --show-info /dev/$number | grep 'type:' | cut -d ":" -f2 |  sed -e 's/^[ \t]*//' | sed 's/ //g')
				if [[ $TYPE == "" ]]; then
					TYPE=$(blkid /dev/$number'1' | cut -d " " -f4 | cut -d'"' -f2)
					if [[ $TYPE == "" ]]; then
						TYPE=$(udevadm info --query=all --name=$number | grep 'ID_PART_TABLE_TYPE' | cut -d '=' -f2)
					fi
				fi
	
				if ! [[ $TYPE ]]; then
					TYPE="UNKNOWN"
				fi
				# Debugging detected size in bytes.
				# echo "BYTES: $BYTES"
				SIZE=$BYTES
				FORMATTED=$(echo $BYTES | \
sed -r '
  :L
  s=([0-9]+)([0-9]{3})=\1,\2=
  t L')
				# IMMEDIATELY convert to KB, the beginning of our scale.
				KBS=$(echo "scale=2;${BYTES%/*}/1024"|bc)
				# Start with bytes each division of 1024 cycle to next array value MB, GB etc.
				for XX in ${DISKSIZES[@]}
				do
					SIZE=$(echo "scale=2;${SIZE%/*}/1024"|bc)
					# Dump the decimal just to see if we have hit the 1024 or less mark.
					KBS=$(echo $SIZE | cut -d . -f 1)
					# Debugging:
					# echo "TESTINGSIZE: $KBS $XX"
					if [[ $KBS -lt 1024 && $KBS -gt 1 ]]; then
						TRUESIZE="$KBS"$XX
						#echo "$KBS $XX"
						
					fi
				done
	
				LABEL=$(echo $LABEL | sed "s/ /_/g")
				# Test against UNKNOWN VALUES
				if ! [[ $TYPE == 'UNKNOWN' || $LABEL == 'UNKNOWN' ]]; then
					# Print data in nice Columns, eventually I will re-write this function
					# to handle data of any size and include it in code-cleanup application.
						if [[ $ZD == "" ]]; then
							DEVICEVALUES+=$(echo "TRUE" "$number" "$LABEL" "$VENDOR" "$TRUESIZE" " ")
							ZD=1
						else
							DEVICEVALUES+=$(echo "FALSE" "$number" "$LABEL" "$VENDOR" "$TRUESIZE" " ")
						fi
				fi
				array_counter=$(($array_counter + 1))
	
		done
		echo "$DEVICEVALUES"
		ans=$(zenity  --width=540 --height=300 --title "ThumbOS" --list  --text "Load $1 to device?" --radiolist  --column "" --column "DEVICE"  --column "LABEL" --column "VENDOR" --column "SIZE" $DEVICEVALUES); echo $ans
		if [[ $ans != "" ]]; then
			if [[ $2 == "--load" ]];then
				Loadit $1 $ans
			fi
			if [[ $2 == "--erase" ]]; then
				EraseType $ans
			fi

		fi
	else
		# OOPSSY end user does not have a thumbdrive.
		Error "Error: No thumbdrive(s) detected.  Exiting..."
		exit 0;
	fi
}

function copyFile(){
	# uncomment below for debugging.
	# echo "copyFile RECIEVED 1:$1 2:$2 3:$3 4:$4"
	inFile="$1"
	outFile="$2"
	wholeCurrentSize="$3"

	# Size in blocks
	size=$(stat --format=%s "$inFile")
	((stepNb = size / blockSize + 1))

	# Prior existance Remove file.
	if [ -f "$outFile" ]; then
		rm "$outFile"
	fi

	# Initiate Copying
	i=0
	while [ "$i" -lt "$stepNb" ]; do
		dd if="$inFile" bs="$blockSize" skip="$i" seek="$i" of="$outFile" count=1 2> /dev/null 
		((i = i + 1))
		# output current copied size
		local copiedSize=$(stat --format=%s "$outFile")
		((totalCopiedSize = copiedSize + wholeCurrentSize)) || true
		((percent = (totalCopiedSize * 100) / totalSize)) || true
		echo -en "$percent%\r"
	done
	return 0
}

function progressCp(){
	# uncomment below for debugging.
	# echo "progressCp Switches RECEIVED 1:$1 2:$2 3:$3 4:$4"
	totalSize=$(du -s "$1" --bytes | awk '{print $1}')
	currentSize=0

	targetDir="$2"
	mkdir -p "$targetDir"
	targetDir=$(readlink -f "$targetDir")

	cd "$1"
	fileList=$(find .)
	INDICATOR='='
	while read inFile; do
		if [ "$inFile" != '.' ]; then
			outFile="$targetDir/$inFile"

			fileSize=$(stat --format=%s "$inFile")

			if [ -d "$inFile" ]; then
				mkdir -p "$outFile"
			elif [ -f "$inFile" ]; then
				if [ "$fileSize" -lt "$blockSize" ]; then
					cp "$inFile" "$outFile"
				else
					copyFile "$inFile" "$outFile" "$currentSize"
				fi
			else
				Error "Error: Unknown type of '$inFile' !" >&2
				exit 1
			fi

			# Mode
			#chmod "$(stat --format=%a "$inFile")" "$outFile"

			# Progress spinner and precentage
			i=1
			sp="/-\|"
			echo -n ' '
			((currentSize = currentSize + fileSize)) || true
			((percent = (currentSize * 100) / totalSize)) || true
			echo -en "$percent%\r" 
		fi
	done < <(echo "$fileList")
}

function UnmountIso(){
	RETURN="$?"

	set +o errexit # We need to clean up everything we can

	trap - HUP QUIT KILL SEGV PIPE INT TERM EXIT

	echo "Syncing..."
	cd /
	sync
	wait 2> /dev/null
	sleep 1

	echo -e "${bldgrn}Umounting and removing '$1'...${txtrst}"
	umount "$1" && rm -rf "$1" || true

	echo -e "${bldgrn}Umounting and removing '$2'...${txtrst}"
	umount "$2" && rm -rf "$2" || true
}

function STARTTIMER {
	# Start the counter, we are off to the races.
	STARTM=`date -u "+%s"`
}

function STOPTIMER {
	STOPM=`date -u "+%s"`
	RUNTIMEM=`expr $STOPM - $STARTM`
	if (($RUNTIMEM>59)); then
		TTIMEM=`printf "%dm%ds\n" $((RUNTIMEM/60%60)) $((RUNTIMEM%60))`
	else
		TTIMEM=`printf "%ds\n" $((RUNTIMEM))`
	fi
	echo "Execution Time: $TTIMEM"
}

function EraseType () {
if [[ $1 ]]; then
	ans=$($GUI --width=540 --height=300 --title "ThumbOS" --list  --text "Which type of erase would you like to do in $1?" --radiolist  --column "" --column "ACTION" TRUE "Quick erase" FALSE "Full erase" FALSE "Secure erase"); echo $ans
case "$ans" in
		"Full erase") echo -e "${txtwht}Full wiping drive: $1"; gksudo dcfldd if=/dev/zero of=/dev/$1 | zenity --progress --title "Erasing device: $1" --text="Full Erasing device $1, Please wait..." --pulsate --auto-kill;;
		"Secure erase") echo -e "${txtwht}Securely wiping drive: $1"; gksudo dcfldd if=/dev/zero of=/dev/$1 | zenity --progress --title "Securely Erasing device: $1" --text="Securely Erasing device $1, Please wait..." --pulsate --auto-kill;;
		*) echo -e "${txtwht}Quickly wiping drive: $1"; QUICK=$(gksudo mkfs.msdos -I -n 'Blank' -F 32 /dev/$1);;
	esac
fi
}

function QuickWipeFat() {
	#Display initial header
	VersionDump
	#Verify the switch interpreter, if not provide short help message example.
	if [[ $1 == "" ]]; then
		DumpArray $1
		Error "ERROR: Please specify a device to wipe."
		Encapsulate "Example: thumbos --erase /dev/sdb"
		Encapsulate "Note: the partition number is unecessary as it will erase the entire drive."
		exit 0;
	fi
	#Begin scanning for USB Devices.
	Encapsulate "SCANNING FOR USB DRIVE(S)..."
	DETECTED=$(ls -l /dev/disk/by-id/*usb* 2> /dev/null)
	#None found?
	if ! [[ $DETECTED ]]; then
		Error "No USB drives detected. Exiting."
		exit 0;
	fi
	if [[ -b /dev/$1 ]]; then
		DumpArray $1
	else
		Error "Error: Device /dev/$1 is not vaild block device."
		Encapsulate "Example usage: thumbos --erase sdk full"
		FullBar
		exit 0;
	fi
	NUMERALS=$(echo $2 |grep -o '[0-9]*')
	if [[ $NUMERALS ]]; then
		Error "Error: Please provide drive letters only no numerals."
		exit 0;
	fi
	#Final check.  Did the user specify a valid device?
	array_counter=1
	for number in ${USBDRIVE[@]}
	do
		REMOVABLE='2'
		REMOVABLE=$(lsblk | grep -m1 $number | cut -d ':' -f2 | cut -d" " -f3)
		#Debugging - future implementation?
		#if [[ $REMOVABLE == 1 ]]; then
			if [[ $number == $1 ]]; then
				VALIDITY='YES'
			fi
		#fi
	done
	
	if [[ $VALIDITY ]]; then
		if [[ $2 == "full" ]]; then
			ETYPE='Full'
		elif [[ $2 == 'secure' ]]; then
			ETYPE='Secure'
		else
			ETYPE='Quick'
		fi
		#Verify write premissions to drive
		THUMBDRIVE="/dev/"$1
		echo -e -n "${txtwht}Verifying write permission of thumbdrive: /dev/$1: ${txtrst}"
		if [[ -w ${THUMBDRIVE} ]]; then
			echo -e "${bldgrn}Granted.${txtrst}"
		else
			echo -e "${bldred}Denied.${txtrst}"
			Error "Please run the command gksudo thumbos --erase $@"
			Encapsulate "Exiting."
			FullBar
			exit 0
		fi
		#User has provided valid switches / permission. Drop information and final warning in bold red to standout.

		echo -e "${bldgrn}$ETYPE Erase: /dev/$1 thumbdrive?${txtwht}"
			while true; do
				FullBar
				echo -e -n "${bldred}"
				read -p "WARNING: this will erase all content on device /dev/$1. (Y/N)? " yn
				case $yn in
					[Nn]* ) echo -e "${txtrst}"; exit 0;;
					[Yy]* ) echo -e "${txtgrn}"
					echo "Erasing $1 thumbdrive...";
					break;;
					* ) echo "Please answer y or n.";;
				esac
			done
	else
		Error "ERROR: $1 is not a valid device."
		exit 0;
	fi
	STARTTIMER
	UNMOUNT=$(umount /dev/$1 2>/dev/null)

	case "$ETYPE" in
		Full) echo -e "${txtwht}Full wiping drive: $1"; gksudo dcfldd if=/dev/zero of=/dev/$1 | zenity --progress --title "Erasing device: $1" --text="Full Erasing device $1, Please wait..." --pulsate --auto-kill;;
		Secure) echo -e "${txtwht}Securely wiping drive: $1"; gksudo dcfldd if=/dev/zero of=/dev/$1 | zenity --progress --title "Securely Erasing device: $1" --text="Securely Erasing device $1, Please wait..." --pulsate --auto-kill;;
		*) echo -e "${txtwht}Quickly wiping drive: $1"; QUICK=$(gksudo mkfs.msdos -I -n 'Blank' -F 32 /dev/$1);;
	esac
	echo -e "${txtwht}Syncing..."
	sync
	echo -e "${txtwht}Refreshing partition ..."
	gksudo partprobe /dev/$1 2> /dev/null
	Notification "All operations completed successfully."
	STOPTIMER
}

function Clear() {

	# Wipe Thumbdrive
	# Debugging switches... Uncomment to see output.
	# echo "1:$1 2:$2 3:$3 4:$4"
	# exit 0;
	# FORCE is an internally called switch to format drive in preparation
	# for loading out M$ Windows.

	if [[ $2 != "FORCE" ]]; then
		# Display initial header
		VersionDump
		# Verify the switch interpreter, if not provide short help message example.
		if [[ $1 == "" ]]; then
			DumpArray $1
			Error "ERROR: Please specify a device to wipe."
			Encapsulate "Example: thumbos --erase sdh"
			Encapsulate "Note: the partition number is unecessary as it will erase the entire drive."
			FullBar
			Help "erase" -e -e
			exit 0;
		fi
		# Begin scanning for USB Devices.
		Encapsulate "SCANNING FOR USB DRIVE(S)..."
		DETECTED=$(ls -l /dev/disk/by-id/*usb* 2> /dev/null)
		# None found?
		if ! [[ $DETECTED ]]; then
			Error "No USB drives detected. Exiting."
			exit 0;
		fi
		if [[ -b /dev/$1 ]]; then
			DumpArray $1
		else
			DumpArray $1
			Error "Error: Device /dev/$1 is not vaild block device."
			Encapsulate "Example usage: thumbos --erase sdk full"
			FullBar
			exit 0;
		fi
		NUMERALS=$(echo $2 |grep -o '[0-9]*')
		if [[ $NUMERALS ]]; then
			Error "Error: Please provide drive letters only no numerals."
			exit 0;
		fi
		#Final check.  Did the user specify a valid device?
		array_counter=1
		for number in ${USBDRIVE[@]}
		do
			REMOVABLE='2'
			REMOVABLE=$(lsblk | grep -m1 $number | cut -d ':' -f2 | cut -d" " -f3)
			#Debugging - future implementation?
			#if [[ $REMOVABLE == 1 ]]; then
				if [[ $number == $1 ]]; then
					VALIDITY='YES'
				fi
			#fi
		done
		
		if [[ $VALIDITY ]]; then
			if [[ $2 == "full" ]]; then
				ETYPE='Full'
			elif [[ $2 == 'secure' ]]; then
				ETYPE='Secure'
			else
				ETYPE='Quick'
			fi

			#Verify write premissions to drive
			THUMBDRIVE="/dev/"$1
			echo -e -n "${txtwht}Verifying write permission of thumbdrive: /dev/$1: ${txtrst}"
			if [[ -w ${THUMBDRIVE} ]]; then
				echo -e "${bldgrn}Granted.${txtrst}"
			else
				echo -e "${bldred}Denied."
				echo -e "Please run the command gksudo thumbos --erase $@"
				echo -e "${txtwht}Exiting.${txtrst}"
				exit 0
			fi

			#User has provided valid switches / permission. Drop information and final warning in bold red to standout.
			echo -e "${bldgrn}$ETYPE Erase: /dev/$1 thumbdrive?${txtwht}"
				while true; do
					FullBar
					echo -e -n "${bldred}"
					read -p "WARNING: this will erase all content on device /dev/$1. (Y/N)? " yn
					case $yn in
						[Nn]* ) echo -e "${txtrst}Exiting..."; exit 0;;
						[Yy]* ) echo -en "${txtgrn}"
						echo "Erasing $1 thumbdrive...";
						break;;
						* ) echo "Please answer y or n.";;
					esac
				done
		else
			Error "ERROR: $1 is not a valid device."
			exit 0;
		fi
	fi
	STARTTIMER
	# Detect number of partitions currently on thumbdrive.
	TOTALPARTS=0
	TOTALPARTS=$(parted -s "/dev/$1" print | tail --lines 2 | grep '^\s[0-9]\+\s\+.*$' | awk '{print $1}'| bc)
	DISKSIZE=$( gksudo parted -s /dev/$1 unit B print | grep "^Disk /dev/$1:" | cut -f 3 -d " " | tr -d B )
	# Information overkill, the end user probably does not care
	# echo "Disk size detected: $DISKSIZE"
	# Unmount Volume(s) - Suppress errors for non-existant volumes
	I=0;
	if [[ $TOTALPARTS -gt 0 ]]; then
		echo -e "${txtwht}$TOTALPARTS existing partitions detected.${txtrst}"
		while [ $I -lt $TOTALPARTS ]; do
			I=$(($I + 1))
			TRUEDEV='/dev/'$1$I
			UNMOUNT=$(umount $TRUEDEV 2>/dev/null)
		done
	else
		echo -e "${txtylw}No existing partitions detected.${txtrst}"
	fi
	#Unmount Success?
	if ! [[ $UNMOUNT ]]; then
		echo -e "${bldgrn}Device $1 successfully unmounted the $TOTALPARTS partition(s).${txtrst}"
		gksudo partprobe /dev/$1  2> /dev/null
	else
		echo -e "${bldred}ERROR: $1 can not be unmounted. Are you root?${txtrst}"
		exit 0;
	fi

	I=0;
	#DUMP ALL PARTITIONS - Do not assume the enduser is in the United States.
	if [[ $TOTALPARTS -gt 0 ]]; then
		while [ $I -lt $TOTALPARTS ]; do
			I=$(($I + 1))
			TRUEDEV='/dev/'$1$I
			echo -e "${txtwht}Deleting partition: $TRUEDEV${txtrst}"
			gksudo parted -s "/dev/$1" rm "$I"
		done
	else 
		echo -e "${txtylw}No partitions to delete.${txtrst}"
	fi
	#Check for non-existant partition table
	ERRORCHECK=$(gksudo parted -s "/dev/$1" print| grep 'unrecognised disk label')
	if [[ $ERRORCHECK ]]; then
		echo -e "${bldred}ERROR: No partition table exists at all, attempting to rectify.${txtrst}"
		sfdisk /dev/$1 << EOF
;
EOF
		gksudo dd if=/dev/zero of=/dev/$1 bs=512 count=1
		gksudo sfdisk -A1 /dev/$1 > /dev/null 2>&1
	fi
	TRUEDEV='/dev/'$11
	#Ensure empty table is reflected to the kernel before proceeding.
	echo -e "${bldgrn}Creating a single partition 100% in size."
	#Suppress standard output, we don't need to update the fstab for a thumbdrive.
	gksudo parted -a opt /dev/$1 unit MB mkpart primary 0% 100% > /dev/null 2>&1
	gksudo sync > /dev/null 2>&1
	gksudo partprobe $TRUEDEV > /dev/null 2>&1

	#Create a single default partition
	I=1
	TRUEDEV='/dev/'$1$I
	#Set default as NTFS
	gksudo sfdisk -c --change-id /dev/$1 1 07 > /dev/null 2>&1
	case "$ETYPE" in
		Full) echo -e "${txtwht}Full wiping drive: $1"; dcfldd if=/dev/zero of=/dev/$1;;
		Secure) echo -e "${txtwht}Securely wiping drive: $1"; dcfldd if=/dev/urandom of=/dev/$1 bs=1M;;
		*) echo -e "${txtwht}Quick formating drive in NTFS Format: $1"; QUICK=$(mkfs.ntfs -Q -L 'ThumbOS' "$TRUEDEV");;
	esac
	if [[ $QUICK ]]; then
		echo -e "${txtwht}Drive $1 successfully formatted.${txtrst}"
	fi
	echo -e "${txtwht}Syncing...${txtrst}"
	gksudo sync
	echo -e "${txtwht}Setting $TRUEDEV as bootable.${txtrst}"
	gksudo sfdisk -A1 /dev/$1 > /dev/null 2>&1
	echo -e "${txtwht}Refreshing partition ...${txtrst}"
	gksudo partprobe /dev/$1  2> /dev/null
	Notification "All operations completed successfully."
	STOPTIMER
}

function WindowsISO {
	echo -e "${bldgrn}©Microsoft Windows ISO detected.${txtrst}"
	# Debugging Switches
	# echo "SENT 1:$1 2:$2 3:$3 4:$4"
	# Exclusive internally called switch to force a wipe, we
	# already know we have a valid device and user has accepted
	# the terms.
	Clear $2 FORCE
	# Create temporary mount points we will clean up later
	isoMountPath="/media/thumbos_iso_$(date +%s)_$$"
	partitionMountPath="/media/thumbos_target_$(date +%s)_$$"
	STARTTIMER
	# Mounting
	REALDEV="/dev/$2"1
	echo "Mounting $1 ISO..."
	mkdir -p "$isoMountPath"
	if [ -f "$1" ]; then # ISO
		mount -o loop "$1" "$isoMountPath"
	else # Real DVD drive (block)
		mount "$1" "$isoMountPath"
	fi
	mkdir -p "$partitionMountPath"
	mount "$REALDEV" "$partitionMountPath"

	# Calculate needed space
	freeSpace=$(df --block-size 1 "$partitionMountPath" | grep "$REALDEV" | awk '{print $4}')
	neededSpace=$(du -s "$isoMountPath" --bytes | awk '{print $1}')
	neededSpace=$((neededSpace + 1000 * 1000 * 30))

	if [ "$neededSpace" -gt "$freeSpace" ]; then
		echo -e "${bldred}Error: Not enough free space on '$REALDEV'!${txtrst}" >&2
		exit 1
	fi

	# Copy data
	echo "Copying ISO data..."
	progressCp "$isoMountPath" "$partitionMountPath"

	# boot dir should be lower case
	if [ -d "$partitionMountPath/BOOT" ]; then mv "$partitionMountPath/BOOT" "$partitionMountPath/boot"; fi
	if [ -d "$partitionMountPath/Boot" ]; then mv "$partitionMountPath/Boot" "$partitionMountPath/boot"; fi

	# Install Grub
	echo "Installing grub, please wait ..."
	grub-install --root-directory="$partitionMountPath" "$REALDEV" > /dev/null 2>&1

	uuid=$(blkid -o value -s UUID "$REALDEV") 

	# grub.cfg 
	echo "Installing grub.cfg..."
	cfgFilename="$partitionMountPath/boot/grub/grub.cfg" 
	mkdir -p "$(dirname "$cfgFilename")"
	echo -n "" > "$cfgFilename"

	echo "echo '------------------------------------'" >> "$cfgFilename" 
	echo "echo '|        ThumbOS - Loading...      |'" >> "$cfgFilename" 
	echo "echo '------------------------------------'" >> "$cfgFilename" 
	echo "insmod ntfs" >> "$cfgFilename" 
	echo "search --no-floppy --fs-uuid $uuid --set root" >> "$cfgFilename" 
	echo "chainloader +1" >> "$cfgFilename" 
	echo "boot" >> "$cfgFilename" 

	# Cleanup and exit
	echo -e "${bldgrn}Cleaning up.${txtrst}"
	UnmountIso "$isoMountPath" "$partitionMountPath" 'Cleanup'
	STOPTIMER
	#Prompt for testing?
	if [[ $QEMUINSTALLED ]]; then
		while true; do
			FullBar
			read -p "Would you like to test the drive now in a virtual machine?. (Y/N)? " yn
			case $yn in
				[Nn]* ) echo -e "${txtrst}"; exit 0;;
				[Yy]* ) echo -e "${txtgrn}"
				echo "Booting $2...";
				break;;
				* ) echo "Please answer y or n.";;
			esac
		done
		Virtual $REALDEV
	fi
	Notification "All operations completed successfully."
}

function Loadit() {
	#Display initial header
	VersionDump

	#Verify the switch interpreter, if not provide short help message example & exit.
	if [[ $1 == "" ]]; then
		Error "ERROR: Please specify an ISO to load to thumbdrive."
		Encapsulate "Example: thumbos --load ultimate-edition-4.0-x64.iso sdc"
		Encapsulate "Note: the partition number is unecessary as it will replace the entire drive."
		FullBar
		Help "load" -e -e
		exit 0;
	fi

	#display information about selected iso:
	if [[ -e $1 ]]; then 
		DiskImageInfo $1
	else
		Error "$1 does not exist. Please specify an ISO to load."
		exit 0;
	fi

	#Begin scanning for USB Devices.
	Encapsulate "SCANNING FOR USB DRIVE(S)..."
	DETECTED=$(ls -l /dev/disk/by-id/*usb* 2> /dev/null)
	#None found?
	if [[ $DETECTED == "" ]]; then
		Error "No USB drives detected. Exiting."
		exit 0;
	fi
	#proper switches provided?
	if ! [[ -e $1 && $2 != "" ]]; then
		if [[ -e "$1" ]]; then
			if [[ ${USBDRIVE[@]} && $2 == "" ]]; then
				Error "Please provide one of the destinations above."
				Encapsulate "Example: thumbos --load ultimate-edition-4.0-x64.iso sdc"
				Encapsulate "Note: the partition number is unecessary as it will replace the entire drive."
				FullBar
				Help "load" -e -e
				exit 0;
			fi
		else
			Error "$1 does not exist. Please specify an ISO."
			exit 0;
		fi

	fi
	#Scan for partition numbers a no, no.
	NUMERALS=$(echo $2 |grep -o '[0-9]*')
	if [[ $NUMERALS ]]; then
		echo -e "${bldred}Error: Please provide drive letters only no numerals.${txtrst}"
		exit 0;
	fi
	#Final check.  Did the user specify a valid device?
	array_counter=1
	for number in ${USBDRIVE[@]}
	do
		REMOVABLE='2'
		REMOVABLE=$(lsblk | grep -m1 $number | cut -d ':' -f2 | cut -d" " -f3)
		#Debugging - future implementation?
		#if [[ $REMOVABLE == 1 ]]; then
			if [[ $number == $2 ]]; then
				VALIDITY='YES'
				THUMBDRIVE='/dev/'$2
			fi
		#fi
	done
	if [[ $VALIDITY ]]; then
		# Verify write premissions to drive
		echo -e -n "${txtwht}Verifying write premissions to thumbdrive ${THUMBDRIVE}: ${txtrst}"
		if [[ -w ${THUMBDRIVE} ]]; then
			echo -e "${bldgrn}Granted.${txtrst}"
		else
			echo -e "${bldred}Denied."
			echo -e "Please run the command gksudo thumbos --load $@"
			echo -e "${txtwht}Exiting.${txtrst}"
			exit 0
		fi

		# User has provided valid switches.  Drop information and warning.
		ans=$($GUI --question --text "This will erase the entire drive $2 and load $1 to $2, are you sure?")
		if ! [[ $? ]]; then
			exit 0;
		fi
		# Whack the thumbdrive and load it as requested.
		# Is drive mounted? If so unmount drive. Suppress errors if not
		# mounted.
		# Windows Bootable ISO?
		if [[ $BOOTABLE && $WINISO ]]; then
			WindowsISO $1 $2 $3 $4
		fi
		# Click the timer, we are starting.
		STARTTIMER

		DUMPIT=$(umount /dev/$2 2>/dev/null)

		# convert image to hybrid bootable image.
		isohybrid $1

		# Use dcfldd - forensic based version of dd aka "Disk Destroyer"
		# we like nice toys.
		gksudo dcfldd sizeprobe=if statusinterval=10 bs=4M if=$1 of=/dev/$2 | zenity --progress --title "Dumping $1 to DEVICE: $2" --text="Please wait..." --pulsate --auto-kill
		# dcfldd sizeprobe=if statusinterval=10 bs=4M if=$1 of=/dev/$2

		# Ensure all data even buffered is written to the disk.
		sync

		# Set drive active
		echo -e "${bldgrn}Setting $2 device as bootable.${txtrst}"
		SUPPRESS=$(sfdisk -A /dev/$2 2>/dev/null)
	else
		echo -e "${bldred}$2 is not a vaild device.  Please refer to the table above.${txtrst}"
		# Correction in #1.0.3, no sence in syncing or refreshing the
		# Partition table if an invaild device was specified. Exit.
		exit 0;
	fi
	echo -e "${txtwht}Syncing..."
	sync
	echo -e "${txtwht}Refreshing partition ..."
	gksudo partprobe /dev/$2  2>/dev/null
	Notification "All operations completed successfully."
	STOPTIMER
	#Prompt for testing?
	if [[ $QEMUINSTALLED ]]; then
		while true; do
			FullBar
			read -p "Would you like to test the drive now in a virtual machine?. (Y/N)? " yn
			case $yn in
				[Nn]* ) echo -e "${txtrst}"; exit 0;;
				[Yy]* ) echo -e "${txtgrn}"
				echo "Booting $2...";
				break;;
				* ) echo "Please answer y or n.";;
			esac
		done
		Virtual /dev/$2
	fi
}

function Help() {
	if [[ $2 == "" ]]; then
		if [[ $1 == "" ]];
		then
			VersionDump
			PRAM="ALL"
		else
			VersionDump
			PRAM=$1
		fi
	else
		PRAM=$1
	fi
	case $PRAM in
		ALL)
		echo -e "${bldgrn}Usage: $PROGNAME -<-COMMAND> [option]${txtrst}"
		FullBar
		echo "Mandatory arguments to long options are identical for short options."
		echo "	possible commands...		"
		echo ""
		echo "	-e	--erase		erases the entire thumbdrive"
		echo "	-l	--load		load ISO image to thumbdrive"
		echo "	-h	--help		this help message"
		echo "	-s	--scan		scans / reports thumbdrive(s) and exits"
		echo "	-t	--test		test boot device and exit"
		echo "	-v	--version	dump version info"
		echo ""
		echo -e "${bldgrn}$PROGNAME --help [COMMAND] for further information.${txtrst}";;
		ALL|e|erase)
		echo -e "${bldwht}Usage erase;${txtrst}"
		FullBar
		echo -e "${txtgrn}$PROGNAME -e <DEVICE> [quick|secure|full]${txtrst}"
		echo "  Quickly erases the contents of <DEVICE> thumbdrive."
		echo -e "  Example: ${bldgrn}$PROGNAME --erase sdi secure${txtrst}"
		echo "  If the [full] or [secure] option is used it will wipe the entire drive. This"
		echo "  is a  slow process and the information is non-recoverable. Specifing no option"
		echo "  is the same as using the default [Quick] option. "
		echo ""
		echo -e "  ${bldred}Warning: The contents of the device will be entirely wiped and"
		echo -e "  unrecoverable using the secure or full option.${txtrst}"
		echo ""
		echo -e "  ${txtylw}Note: The partition number is not necessary as the entire drive will be wiped.${txtrst}";;
		ALL|s|scan)
		echo -e "${bldwht}Usage scan;${txtrst}"
		FullBar
		echo -e "${txtgrn}$PROGNAME -s${txtrst}"
		echo "  Scans and reports available thumbdrive(s).";;
		ALL|t|test)
		echo -e "${bldwht}Usage test;${txtrst}"
		FullBar
		echo -e "${txtgrn}$PROGNAME -t [DEVICE|ISO]${txtrst}"
		echo "  Invokes a virtual machine to boot [DEVICE] or [ISO] image."
		echo "  Example: thumbos --test ultimate-edition-4.2-x64-lite.iso"
		echo "  Example 2: thumbos --test sdd";;
		ALL|l|load)
		echo -e "${bldwht}Usage load;${txtrst}"
		FullBar
		echo -e "${txtgrn}$PROGNAME -l <ISONAME> <DEVICE>${txtrst}"
		echo "  Loads selected ISO to selected thumbdrive. Optionally will launch kvm for"
		echo "  testing."
		echo ""
		echo -e "  Example: ${bldgrn}thumbos --load utimate-edition-4.0-x64.iso sdi"
		echo -e "  ${bldred}Warning: The contents of the device will be entirely wiped.${txtrst}"
		echo -e "  ${bldylw}Note: the partition number is unecessary as it will replace the entire drive.${txtrst}";;
		ALL|v|version)
		echo -e "${bldwht}Usage version;${txtrst}"
		FullBar
		echo -e "${txtgrn}$PROGNAME -v${txtrst}"
		echo "  Displays $PROGNAME version number and exits.";;
		ALL|h|help|\?)
		echo -e "${bldwht}Useage Help [COMMAND];${txtrst}"
		FullBar
		echo -e "${txtgrn}$PROGNAME -h [COMMAND]${txtrst}"
		echo "  Displays this message. For futher information $PROGNAME help [COMMAND]"
		echo "  or refer to the manpages."
		echo ""
		echo "man $PROGNAME"
		echo -e "${txtgrn}"
		echo -e "Example: $PROGNAME -h version"
		echo -e "${txtwht}Will display help about the command version${txtrst}"
	esac
	FullBar
	exit 0
}

# Command line pre-processor use for debugging.
#CommandLineIntrepreter $@
# BEGIN MAIN PROGRAMMING
function InitialDialog() {
	if [[ $1 ]]; then
		echo "DEBUGGING: $1"
	else
		ans=$($GUI --width=540 --height=300 --title "ThumbOS" --list  --text "What would you like to do?" --radiolist  --column "" --column "ACTION" TRUE "Load disk image to device" FALSE "Test a disk image in a virtual machine" FALSE "Erase an entire thumbdrive"); echo $ans
	fi
	if [[ $ans == 'Test a disk image in a virtual machine' ]]; then
		FILE=$($GUI --file-selection)
		Virtual $FILE
	fi
	if [[ $ans == 'Load disk image to device' ]]; then
		FILE=$($GUI --file-selection)
		DumpArray $FILE --load
	fi
	if [[ $ans == 'Erase an entire thumbdrive' ]]; then
		DumpArray "" "--erase"
	fi

}
if ! [[ $GUI ]]; then
	VersionDump
	Error "Zenity is not installed, no GUI functionality."
	exit 0;
else
	if ! [[ -f $1 ]]; then
		InitialDialog $1
		
	else
		DumpArray $1
	fi
fi
    case "$1" in
      -s|--scan) VersionDump; DumpArray; exit 0;;
      -t|--test) VersionDump; Virtual $2; exit 0;;
      -e|--erase) Clear $2 $3 $4; exit 0;;
      -l|--load) Loadit $2 $3 $4; exit 0;;
      -h|--help|-\?) Help $2; exit 0;;
      -v|--version) VersionDump; exit 0;;
      *) Help; exit 0;;
    esac
