#!/bin/bash
########################################################################
####  Script Name: sm-lib-clean-up
####  version: 2.10.15
####  Date: February 8 2012

####  Copyright (C) Harald Hope 2005-2012
####  The following functions use core logic by Joaquim Boura (x-un-i):
####  msg_on msg_off list_modules remove_the_kernel
####  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.

####  This program 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.

####  Get the full text of the GPL here:
####  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

####  Script Author: Harald Hope
####  This is a library file for smxi and cannot be run independently

####  Script URL: http://smxi.org/sm/sm-lib-clean-up
####  Script SVN: http://code.google.com/p/smxi
####  Script Home page: http://techpatterns.com/forums/about736.html
########################################################################

########################################################################
####  FUNCTIONS
########################################################################

###---------------------------------------------------------------------
### clean up caller function
###---------------------------------------------------------------------
# this one just does various odd little things
clean_up()
{
	eval $LOGMS
	local repeat='' opt='' currentKernelsPrint='' advanced='' xOption='' cont=''
	#local currentKernels=$(dpkg -l | grep headers-2 | cut -d " " -f 3 | cut -d '-' -f 3-9 )
	local currentKernels="$( package_tester 'linux-image-2' 'wild' | sed 's/linux-image-//g' )"
	local options="apt-clean apt-autoclean kernel-remover remove-kernel-modules clean-smxi-stuff debian-orphans remove-xorg-modules clean-cruft "

	local tempCount=$( echo $options | wc -w )

	# I'm leaving this as a template in case I want some -x option stuff later
	# this stuff is now in misc tweaks legacy tweaks
	if [ "$EXTRA_OPTIONS" == 'true' ];then
		# tempCount=$(( $tempCount + 1 ))
		# xOption='clean-kanotix-packages'
		# advanced='echo -e "${C}'$tempCount'${S} - Runs ${C}clean-kanotix-packages${S}. This will clean up any legacy kanotix\n\tpackages left over after your ${C}sidux${S} conversion.\n\tEach item will ask you if you want to remove it, answer y or n."'
		# tempCount=''
		:
	fi
	options="$options $xOption return-main-menu"
	tempCount=$( echo $options | wc -w )

	cont=$(( $tempCount ))

	if [ -z "$currentKernels" ];then
		currentKernels=$CURRENT_KERNEL
	fi

	for x in $currentKernels
	do
		currentKernelsPrint=$currentKernelsPrint' '$x
	done

	print_lib_info $LIB_CLEAN_UP
	echo $MLINE
	echo "${S}Clean up old junk from your install with these options. Please read each option"
	echo "carefully before you run it."
	echo $LINE

	echo "${C}1${S} - Runs the simple command ${C}$APT_TYPE clean${S}."
	echo "    This removes the apt files cached in ${C}/var/cache/apt/archives${S}. They hurt nothing by"
	echo "    remaining, and can be interesting to look at, but they also take up diskspace."

	echo "${C}2${S} - Runs the command ${C}$APT_TYPE autoclean${S}."
	echo "    Like clean, autoclean clears out the local repository of retrieved package files."
	echo "    The difference is it only removes package files that are not in apt."
	echo "    This allows a cache to be maintained over a long period without it getting too big."

	echo "${C}3${S} - ${C}kernel-remover${S}. This removes all kernels ${M}EXCEPT${S} your current kernel: ${C}$CURRENT_KERNEL${S}"
	echo "    The kernel remover will give you the option to keep or delete all non running kernels."

	echo "${C}4${S} - Runs ${C}remove-kernel-modules${S}. This removes any kernel module you want."

	echo "${C}5${S} - Runs ${C}clean-smxi-stuff${S}. Clean various parts that $SCRIPT_NAME has created over time,"
	echo "    including backup files, kernel/graphics driver downloads, and configuration files."

	echo "${C}6${S} - Runs ${C}debian-orphans${S}. This will search your system for orphaned Debian"
	echo "    packages and print out a list of them. It will not remove them, because that's"
	echo "    not safe to do automatically. Always confirm each package manually before removing it."

	echo "${C}7${S} - ${C}remove-xorg-modules${S} will remove unused xorg modules."
	echo "    You will be presented with a list of modules not currently used, and you can"
	echo "    keep whichever you want, and remove the rest."

	echo "${C}8${S} - ${C}clean-cruft${S} will remove any parts of packages you removed via ${C}$APT_TYPE remove${S}"
	echo "    without using ${C}dpkg --purge${S}. Has option to simulate first so you can see what"
	echo "    will happen. These packages are found via ${C}dpkg -l | grep ^rc${S}"

	eval $advanced
	echo
 	echo "${C}$cont${S} - Return to main menu."
	echo $LINE
	echo -e $SLE
	echo $LINE

	select opt in $options
	do
		case $opt in
			apt-clean)
				apt_clean clean
				repeat='true'
				;;
			apt-autoclean)
				apt_clean autoclean
				repeat='true'
				;;
			kernel-remover)
				kernel_remover_main
				repeat='true'
				;;
			remove-kernel-modules)
				run_script_import $LIB_KERNEL
				remove_kernel_modules
				repeat='true'
				;;
			clean-smxi-stuff)
				clean_smxi_stuff
				repeat='true'
				;;
			debian-orphans)
				check_deborphans
				repeat='true'
				;;
			remove-xorg-modules)
				remove_xorg_modules
				repeat='true'
				;;
			clean-cruft)
				clean_cruft
				repeat='true'
				;;
			return-main-menu)
				echo "${S}Returning to main menu.${N}"
				;;
			*)
				print_error opt
				repeat='true'
				;;
		esac
		break
	done
	eval $LOGME
	if [ "$repeat" == 'true' ];then
		clean_up
	fi
}
#clean_up

###---------------------------------------------------------------------
### miscellaneous cleanup utilities
###---------------------------------------------------------------------
clean_cruft()
{
	eval $LOGPS
	local toRemove=$( package_tester '' rc-all )
	local opt='' options=''
	local package='' action='' doIt='' repeat='' actionText='' removeAll=''
	toRemove=$( echo $toRemove ) # dump line breaks

	echo $LINE
	if [ -n "$toRemove" ];then
		echo "${S}Uses ${C}dpkg --purge${S} to remove the following cruft left-overs from your system:"
		echo "${C}$toRemove${N}"
		echo $LINE
		echo "${Q}Do you want to purge all these left over package items?"
		echo $LINE
		echo "${C}1 - yes-remove-one-by-one${S} - Removes each package one at a time."
		echo "${C}2 - yes-remove-all${S} - Removes entire list at once."
		echo "${C}3 - simulate-remove-all${S} - Simulate the removal of all packages."
		echo "${C}4 - return-main-menu${S} - Go back to main menu, skip removals."
		echo $LINE
		echo -e $SLE
		echo $LINE
		options="yes-remove-one-by-one yes-remove-all simulate-remove-all return-main-menu"
		select opt in $options
		do
			case $opt in
				yes-remove-one-by-one)
					doIt='true'
					;;
				yes-remove-all)
					doIt='true'
					removeAll='true'
					;;
				simulate-remove-all)
					doIt='true'
					action='--simulate'
					actionText=' (simulation)'
					removeAll='true'
					repeat='true'
					;;
				return-main-menu)	
					echo "${S}Ok, going back to the main menu now...${N}"
					;;
				*)	print_error 'opt3'
					repeat='true'
					;;
			esac
			break
		done
	
		if [ "$doIt" == 'true' ];then
			log_function_data "toRemove: $toRemove"
			echo $LINE
			if [ "$removeAll" != 'true' ];then
				for package in $toRemove
				do
					echo "${S}Purging$actionText ${C}$package${S} now...${N}"
					dpkg --purge $action $package
				done
			else
				echo "${S}Purging$actionText these packages now:"
				echo "${C}$toRemove${N}"
				dpkg --purge $action $toRemove
			fi
		fi
	else
		echo "${M}No packages found to be purged.${N}"
		print_hec
	fi
	eval $LOGPE
	if [ "$repeat" == 'true' ];then
		clean_cruft
	fi
}

apt_clean()
{
	eval $LOGPS
	local aptcommand=$1 text1=''
	if [ "$1" == 'autoclean' ];then
		text1=' outdated'
	fi

	echo $LINE
	echo "${S}Running the command: ${C}$APT_TYPE $aptcommand${S}."
	echo "${C}$APT_TYPE $aptcommand${S} will remove all the$text1 archived deb files in ${C}/var/cache/apt/archives${S}${N}"
	$APT_TYPE $aptcommand
	echo "${S}Your apt archives have been cleaned in the way you requested.${N}"
	eval $LOGPE
}

check_deborphans()
{
	eval $LOGUS
	local orphanFeature=0

	if [ -z "$( package_tester 'deborphan' )" ];then
		install_missing_apps 'deborphan' 'feature'
		orphanFeature=$?
	fi
	if [ "$orphanFeature" -eq 0 ];then
		eval $LOGUE
		debian_orphans
	else
		eval $LOGUE
	fi
}

# cleans out all orphaned packages from various removals.
debian_orphans()
{
	eval $LOGPS
	local orphan='' keepThese='libgl1-mesa-dri liblame0 '
	local cleanMore='' orphan='' orphanTemp=''
	local orphans=$( deborphan )
	# loop it to break the linebreaks
	for orphan in $orphans
	do
		orphanTemp="$orphanTemp $orphan"
	done
	orphans=$orphanTemp
	log_function_data "orphans: $orphans"
	#[ -z "$( echo $keepThese | grep $orphan )" ] &&

	echo $LINE
	echo "${S}List of items deborphan thinks you don't need."
	echo
	echo "${M}ALWAYS confirm individual packages on this list manually."
	echo "${W}Do not use automated methods to remove these! Breakage can occur if you do.${N}"
	echo $LINE
	echo "${C}$orphans${N}"
	echo $LINE
	echo "${S}You can copy these by highlighting the list, then moving to another terminal"
	echo "using ${C}ctrl+alt+<F2-F6>${S}, assuming you are currently in terminal 1, then"
	echo "pasting them into your favorite text editor like ${C}nano${S} or ${C}mcedit${S} using"
	echo "the center mouse wheel button click to paste into the editor."
	echo
	echo "They are also logged in: ${C}$LOG_FILE${S}"
	echo "Just search for ${C}orphan:${S} in the log file to locate the list."
	echo
	echo "Often multimedia library files are called orphaned even though your systems multimedia"
	echo "use them. So make sure the package is truly obsolete and unused before removing it!"
	print_hec
# 	while orphan=$( deborphan )
# 	test -n "$orphan"
# 	do
# 		package_remover $orphan 'purge -y'
# 	done
#
# 	# run this after the above, this is the old mini-script remove-orphans
#
# 	cleanMore="$( COLUMNS=200 dpkg -l | grep ^rc | awk '{print $2}' )"
# 	if [ -n "$cleanMore" ]
# 	then
# 		dpkg --purge $cleanMore
# 	fi
#
# 	echo "${S}Debian deb orphans have been removed.${N}"
	eval $LOGPE
}
#debian_orphans

###---------------------------------------------------------------------
### kernel remover components
###---------------------------------------------------------------------

kernel_remover_main()
{
	eval $LOGP
	# get list of all installed kernels minus current running one
	local installedKernels=$( ls /boot/vmlinuz-* | sed 's|/boot/vmlinuz-||g' | grep -v $CURRENT_KERNEL )
	local kernelRemoveOptNu=$( wc -w <<< $installedKernels )
	local options="$installedKernels back-to-main-menu" opt=''
	local continueOptNu=$( wc -w <<< $options )
	local kernel='' userSelection='' removeValue=''
	
	log_function_data "installedKernels: $installedKernels"

	echo $MLINE
	echo "${M}Kernel Remover"
	echo $MLINE
	echo "${S}Please select one by one which kernel you want to remove. ${C}$SCRIPT_NAME${S} will also"
	echo "give you the option to remove the ${C}$SCRIPT_NAME${S} kernel download directory it creates each"
	echo "time you install a new kernel after the primary kernel removal option is run."
	echo
	echo "${M}Note: you cannot remove your currently running kernel: ${C}$CURRENT_KERNEL"
	echo
	echo "${S}Always keep at least one known good kernel besides your current kernel."
	echo "To remove your current kernel, you will need to boot into another kernel,"
	echo "then run this option and select the kernel you need removed at that time."

	echo $LINE
	if [ "$kernelRemoveOptNu" -gt 0 ];then
		echo "${C}1-$kernelRemoveOptNu${S} - Remove any one of these installed kernels."
	else
		echo "${M}There are no kernels to remove!"
		echo $LINE
	fi
	echo "${C}$continueOptNu - back-to-main-menu${S} All done? Ok, you can go on now."
	echo $LINE
	echo -e $SLE
	echo $LINE

	select opt in $options
	do
		for kernel in $options
		do
			if [ "$opt" == "$kernel" ];then
				userSelection=$kernel
				break
			fi
		done
		break
	done

	eval $LOGPE
	case "$userSelection" in
		# handle null case first
		'')
			print_error opt
			kernel_remover_main
			;;
		back-to-main-menu)
			echo "${S}Ok, continuing on with script...${N}"
			;;
		*)
			confirm_kernel_removal "$userSelection"
			removeValue="$?"
			if [ "$removeValue" -le 1 ];then
				remove_the_kernel "$userSelection"
				case $removeValue in
					0)
						clean_download_directories 'all'
						;;
					1)
						clean_download_directories "$userSelection"
						;;
				esac
			fi
			# and then repeat
			kernel_remover_main
			;;
	esac
}
# args: $1 - kernel to remove
confirm_kernel_removal()
{
	eval $LOGUS
	local options='' opt='' repeat='' returnValue=''

	echo $LINE
	echo "${Q}Are you sure you want to remove kernel: ${C}$1${Q}?"
	echo $LINE
	echo "${C}1 - yes-remove-kernel${S} - Will ask if you want to remove $SCRIPT_NAME kernel download directories."
	echo "    Note: this will ask if you want to remove directories for all non-installed kernels."
	echo "${C}2 - yes-remove-kernel-and-download-directory${S} - Automatically removes both kernel and"
	echo "    $SCRIPT_NAME kernel download directory (removes only that specific directory)."
	echo "${C}3 - no-do-not-remove${S} - I don't want to remove the kernel, return to kernel removal menu."
	echo $LINE
	echo -e $SLE
	echo $LINE
	options="yes-remove-kernel yes-remove-kernel-and-download-directory no-do-not-remove"
	select opt in $options
	do
		case $opt in
			yes-remove-kernel)
				returnValue=0
				;;
			yes-remove-kernel-and-download-directory)
				returnValue=1
				;;
			no-do-not-remove)
				returnValue=2
				;;
			*)
				print_error opt
				repeat='true'
				;;
		esac
		break
	done
	eval $LOGUE

	if [ "$repeat" == 'true' ];then
		confirm_kernel_removal "$1"
	else
		return $returnValue
	fi
}

# args: $1 - kernel to remove
remove_the_kernel()
{
	eval $LOGUS
	local kernelToRemove=$1
	local kernelCleaned=$( sed 's/\-sidux.*$//' <<< $kernelToRemove )
	# need to remove headers/image metapackages if installed to avoid reinstalling package
	local metaImagePackage=$( grep-available -F Depends linux-image-$kernelToRemove -s Package | awk '{print $2}' )
	local metaHeadersPackage=$( grep-available -F Depends linux-headers-$kernelToRemove -s Package | awk '{print $2}' )
	local removeList="$( package_tester "$kernelToRemove" 'wild-full' )"

	if [ "$kernelToRemove" != "$kernelCleaned" ];then
		# saw a weird glitch where apt-get recieves a -all package that doesn't exist, dpkg must show it
		removeList="$removeList $( package_tester "$kernelCleaned-common" 'wild-full' | grep -v '\-all' )"
		removeList="$removeList $( package_tester "linux-support-$kernelCleaned" 'wild-full' )"
	fi
	removeList="$removeList $metaHeadersPackage $metaImagePackage"
	# echo removeList: $removeList
	log_function_data "removeList: $removeList"
	echo $LINE
	echo "${S}Removing all ${C}$kernelToRemove${S} kernel packages now...${N}"
	package_remover "$removeList" 'purge -y' 'group'

	echo "${S}Cleaning up any leftover kernel cruft from ${C}$kernelToRemove${S} now...${N}"
	# dump empty directories/linux-headers if present, sometimes these are
	# left over after the operation for various reasons
	if [ ! -e "/boot/vmlinuz-$kernelToRemove" ];then
		rm -rf /lib/modules/$kernelToRemove
		rm -rf /usr/src/linux-headers-$kernelToRemove
	fi
	echo "${S}Running ${C}update-grub${S} to make sure everything is solid...${N}"
	update-grub
	echo
	echo "${S}Your kernel removal action for ${C}$kernelToRemove${S} has been completed.${N}"

	eval $LOGUE
}

# args: $1 - all/kernel version
clean_download_directories()
{
	eval $LOGUS
	local kernelRemoval=$1
	local subDirectories='' directory=''
	local subDirectories=$( ls $SM_KERNEL_DOWNLOAD_DIRECTORY 2>/dev/null )
	local kernelStringMatch=''

	echo $LINE

	if [ -d $SM_KERNEL_DOWNLOAD_DIRECTORY -a -n "$subDirectories" ];then
		case $kernelRemoval in
			all)
				for directory in $subDirectories
				do
					# this handles new randomness in kernel naming conventions
					kernelStringMatch=$( test_kernel_strings $directory )
					if [ "$directory" != "$CURRENT_KERNEL" -a "$kernelStringMatch" != 'true' ];then
						remove_the_directory $SM_KERNEL_DOWNLOAD_DIRECTORY $directory
					fi
				done
				;;
			*)
				if [ -d $SM_KERNEL_DOWNLOAD_DIRECTORY/$kernelRemoval ];then
					remove_the_directory $SM_KERNEL_DOWNLOAD_DIRECTORY $kernelRemoval 'single'
				else
					echo "${M}Kernel directory: ${C}$SM_KERNEL_DOWNLOAD_DIRECTORY/$kernelRemoval${M} does not exist.${N}"
					log_function_data "Directory $kernelRemoval was not found so not removed."
				fi
				;;
		esac
	else
		echo "${E}No kernel install directories were located.${N}"
		log_function_data "no kernel install directories detected"
	fi
	eval $LOGUE
	# print_hec
}

# args: $1 kernel download main directory; $2 sub directory name; $3 - single [optional]
remove_the_directory()
{
	eval $LOGUS
	local options='' opt='' repeat='' removeIt=''
	# quick hack to handle legacy kernel syntax in grub, changing back to old syntax here
	local grubTester=$( echo $2 | sed -e 's/\.slh\./-slh.*-/' | sed -r 's/(-(aptosid|sidux)-(686|amd64))//' )
	local kernelInGrub=$( grep $2 $GRUB_PATH )
	local cleanedKernelInGrub=$( grep -E $grubTester $GRUB_PATH )

	log_function_data "Remove the kernel install directory $1/$2\nkernelInGrub: $kernelInGrub\ncleanedKernelInGrub: $cleanedKernelInGrub"

	# test to see if kernel is in /boot/grub/menu.lst, if not, offer to remove
	if [ -z "$kernelInGrub" -a -z "$cleanedKernelInGrub" ];then
		echo $LINE
		if [ "$3" != 'single' ];then
			echo "${Q}Do you want to remove the kernel install directory ${C}$1/$2"
			echo $LINE
			echo -e $SLE
			echo $LINE
			options="yes-remove-install-directory no-keep-install-directory"
			select opt in $options
			do
				case $opt in
					yes-remove-install-directory)
						removeIt='true'
						;;
					no-keep-install-directory)
						echo "${S}Continuing without removing directory: ${C}$1/$2${N}"
						returnValue=1
						;;
					*)
						print_error opt
						repeat='true'
						;;
				esac
				break
			done
		fi
		if [ "$removeIt" == 'true' -o "$3" == 'single' ];then
			echo "${S}Removing kernel directory: ${C}$1/$2${S}...${N}"
			rm -fr $1/$2 && returnValue=0 || returnValue=2
		fi

		log_function_data "Return Value: $returnValue"
		eval $LOGUE
		if [ "$repeat" == 'true' ];then
			remove_the_directory "$1" "$2"
		else
			return $returnValue
		fi
	else
		# don't use this, because for looping, it doesn't handle it right
		:
# 		echo "${E}Kernel ${C}$1${E} is still in ${C}$GRUB_PATH"
# 		echo "${S}This is an error, please let the $SCRIPT_NAME maintainer know.${N}"
# 		log_function_data "Kernel in grub: Return Value: 3"
# 		eval $LOGUE
# 		return 3
	fi
}

###---------------------------------------------------------------------
### clean xorg section
###---------------------------------------------------------------------

# this logic is based on original methods by x-un-i
list_xorg_modules()
{
	eval $LOGUS
	local moduleList='' moduleType='' module=''  moduleLoaded=''
	if [ -f /var/log/Xorg.0.log ];then
		local installedXorgPackages="$( dpkg -l | grep xserver-xorg | awk '{ print $2 }' )"
		local runningModules="$( grep -is 'LoadModule' /var/log/Xorg.0.log | sed -e 's/\"//g' | awk '{ print $NF }' )"
		runningModules="vesa dummy $runningModules"
		local currentName=''
		local isNvidia=$( grep -ic 'nvidia' <<< "$runningModules" )
		local isFglrx=$( grep -ic 'fglrx' <<< "$runningModules" )

		# first strip out the nv/radeon/radeonhd modules
		if [ "$isNvidia" -ge 1 ];then
			installedXorgPackages=$( sed -e 's/xserver-xorg-video-nv//' -e 's/xserver-xorg-video-nouveau//' <<< "$installedXorgPackages" )
		fi
		if [ "$isFglrx" -ge 1 ];then
			# note: if the fglrx driver is loaded, it's NOT an ati/r128/mach64 type card
			# since fglrx does not support those cards
			# installedXorgPackages=$( sed 's/xserver-xorg-video-ati//' <<< "$installedXorgPackages" )
			# make radeonhd removed first, otherwise you might end up with 'hd' alone
			installedXorgPackages=$( sed 's/xserver-xorg-video-radeonhd//' <<< "$installedXorgPackages" )
			installedXorgPackages=$( sed 's/xserver-xorg-video-radeon//' <<< "$installedXorgPackages" )
		fi

		for module in $installedXorgPackages
		do
			# slice out the part after 'input-' or 'video-'
			currentName=${module##*input-}
			if [ "$currentName" == "$module" ];then # filter the word video
				currentName=${module##*video-}
				if [ "$currentName" == "$module" ];then # filter the word video
					moduleType='undef'
				else
					moduleType='video'
				fi
			else
				moduleType='input'
			fi

			if [ "$moduleType" == "undef" ];then
				if [ "$B_TESTING_1" == 'true' ];then
					echo "Xorg module calculations: skipping $moduleType..."
				fi
			else
				if [ "$B_TESTING_1" == 'true' ];then
					echo "Xorg module calculations: Module $currentName is $moduleType"
				fi
				# now if the module is in the loaded list we skip it
				# otherwise we add it to the list of modules to be removed
				moduleLoaded=$( grep -ic $currentName <<< "$runningModules" )
				# note: this needs to be > 1 because 2 fglrx modules can be loaded
				if [ "$moduleLoaded" -ge 1 ];then
					if [ "$B_TESTING_1" == 'true' ];then
						echo "Module $module : type $moduleType : Status: currently used"
					fi
				else
					if [ "$B_TESTING_1" == 'true' ];then
						echo  "Module $module : type $moduleType : Status: not currently used"
					fi
					# not sure about xorg 1.6, so just keeping these in case they are needed
					# note: removing input-evdev removes ALL xorg, so needs to be filtered out, jiro found this
					if [ -z "$( grep -Ei '(input-kbd|input-mouse|input-evdev)' <<< $module )" ];then
						moduleList="$moduleList $module"
					else
						if [ "$B_TESTING_1" == 'true' ];then
							echo  "Skipping module $module : type $moduleType"
						fi
					fi
				fi
			fi
		done
	else
		moduleList='no-xorg-log'
	fi
	# return the data and log it
	echo "$moduleList"
	log_function_data "moduleList: $moduleList"
	eval $LOGUE
}
# list_modules

# this is based on x-un-i's script, clean_xorg_modules.sh, slightly modified version used
# remove extra xorg modules
remove_xorg_modules()
{
	eval $LOGPS
	local back='' StartOver='' found='' remove='' LeaveLoop=''

	X_ORG_SAVE_LIST='' # must be reset every round to handle start over
	if [ "$B_TESTING_1" != 'true' ];then
		X_ORG_LIST=$( list_xorg_modules )
	else
		list_xorg_modules
	fi
	if [ "$X_ORG_LIST" != 'no-xorg-log' ];then
		local XorgListOpt="$X_ORG_LIST remove-modules start-over back-to-main-menu"
		local RemoveModules=$( echo $XorgListOpt | awk '{ print NF-2 }' )

		echo $MLINE
		echo "${M}CLEAN XORG MODULES"
		echo $LINE
		echo "${S}Please read through this list carefully. If one of the xorg modules should"
		echo "not be removed, please enter its number and hit enter. Do this until you have"
		echo "listed all the modules you don't want removed. You are not currently using any of"
		echo "the listed modules. But if you want to keep some anyway, that is an option."
		echo "To remove all of them, simply enter ${C}$RemoveModules${S} for ${C}remove-modules${S}"
		echo $LINE
		echo "${S}Remember, if the screen scrolls out of sight, you can always"
		echo "go back up or down by hitting: ${C}shift+pageup/pagedown"
		echo $LINE

		options=$XorgListOpt
		LoopList=$XorgListOpt

		select opt in $options
		do
			for item in $LoopList
			do
				if [ "$opt" == "$item" ];then
					case $item in
						start-over)
							StartOver='true'
							LeaveLoop='true'
							;;
						back-to-main-menu)
							back='true'
							LeaveLoop='true'
							StartOver='false'
							;;
						remove-modules)
							remove='true'
							LeaveLoop='true'
							StartOver='false'
							;;
						*)
							X_ORG_SAVE_LIST="$X_ORG_SAVE_LIST $item"
							echo "${S}You have elected to keep the following unused xorg modules:${C}"
							echo $X_ORG_SAVE_LIST
							echo "${S}Please select another module to keep, or enter ${C}$RemoveModules${S} to remove all non-selected xorg modules now.${N}"
							StartOver='false'
							;;
					esac
					break
				else
					StartOver='true'
				fi
			done
			if [ "$LeaveLoop" == 'true' ];then
				break
			fi
		done

		if [ "$StartOver" == 'true' ];then
			remove_xorg_modules
		elif [ "$back" == 'true' ];then
			echo $LINE
			echo "${S}Returning to post-$DU_UPGRADE options.${N}"
		elif [ "$remove" == 'true' ];then
			remove_xorg_components
		fi
	else
		echo $ELINE
		echo "${E}No ${C}Xorg.0.log${E} file exists, which means you have probably never started Xorg before."
		echo "${S}Cannot run this function until you have started X (your desktop) at least one time!${N}"
		print_hec
	fi
	eval $LOGPE
}

remove_xorg_components()
{
	eval $LOGUS
	local XorgListRemove='' keep='' item=''

	for keep in $X_ORG_SAVE_LIST
	do
		for item in $X_ORG_LIST
		do
			if [ "$keep" != "$item" ];then
				XorgListRemove="$XorgListRemove "$item
			fi
		done
		X_ORG_LIST=$XorgListRemove
		XorgListRemove=''
	done

	echo $LINE

	if [ "$X_ORG_LIST" != '' ];then
		echo "${S}Running ${C}$APT_TYPE purge${S} on the modules you did not preserve.${N}"
		log_function_data "X_ORG_LIST: $X_ORG_LIST"
		package_remover "$X_ORG_LIST" 'purge' 'group'
		echo "${S}The following ${C}xorg modules${S} have been removed:"
		echo "${C}$X_ORG_LIST"
		echo $LINE
		# make logfile for operation
		write_xorg_remove_log
		echo "${S}You can find a list of the removed modules here: ${C}$CLEAN_X_ORG_LOG${N}"
	else
		echo "${E}No modules are left to remove after your selections.${N}"
	fi
	eval $LOGUE
}

write_xorg_remove_log()
{
	eval $LOGUS
	local item=''

	if [ ! -f $CLEAN_X_ORG_LOG ];then
		touch $CLEAN_X_ORG_LOG
	fi
	echo $LINE >> $CLEAN_X_ORG_LOG
	echo 'The following Xorg Modules were removed on '$(date +%y-%m-%d)':' >> $CLEAN_X_ORG_LOG
	echo >> $CLEAN_X_ORG_LOG
	for item in $X_ORG_LIST
	do
		echo $item >> $CLEAN_X_ORG_LOG
	done
	echo $LINE >> $CLEAN_X_ORG_LOG
	eval $LOGUE
}
#remove_xorg_modules

###---------------------------------------------------------------------
### clean smxi data/backups section
###---------------------------------------------------------------------

# args: $1 - y-option (optional)
clean_smxi_stuff()
{
	local repeat='' opt='' lastOption='return-main-menu' 
	local lastOptionText='Go back to main menu.'
	local lastOptionExit='Returning to main menu.'
	if [ "$1" == 'y-option' ];then
		lastOption='quit-cleanup'
		lastOptionText='Exit cleanup.'
		lastOptionExit='Exiting cleanup.'
	fi
	local options="remove-backup-files remove-xorg.conf-backup-files remove-kernel-downloads remove-video-driver-downloads remove-virtual-machine-downloads remove-log-files remove-script-configuration-files uninstall-smxi uninstall-all-smxi-scripts $lastOption"

	echo $MLINE
	echo "${M}$SCRIPT_NAME cleanup tool"
	echo $MLINE
	
	echo "${S}Each cleanup item will ask you to confirm your choice before deleting the requested"
	echo "files, and will show you what it will delete to make sure you don't accidentally"
	echo "remove something you wanted to keep."
	
	echo $LINE
	echo "${C}1 - remove-backup-files${S} - Delete all $SCRIPT_NAME generated backup files."
	echo "    This can be useful to run now and then since some tasks tend to collect backup files."
	echo "${C}2 - remove-xorg.conf-backup-files${S} - Delete all sgfxi generated backup files."
	echo "${C}3 - remove-kernel-downloads${S} - Remove the kernel downloads directory."
	echo "${C}4 - remove-video-driver-downloads${S} - Remove the video driver downloads directory."
	echo "${C}5 - remove-virtual-machine-downloads${S} - Remove virtual machine download directory."
	echo "${C}6 - remove-log-files${S} - Delete all $SCRIPT_NAME, svmi, and sgfxi log files."
	echo "${C}7 - remove-script-configuration-files${S} - Remove all script configuration files."
	echo "    Not recommended since then if you run the script again you have to run throught the"
	echo "    setup routine all over again."
	echo "${C}8 - uninstall-smxi${S} - Uninstalls $SCRIPT_NAME, then removes"
	echo "    all connected files from $SCRIPT_HOME"
	echo "${C}9 - uninstall-all-smxi-scripts${S} - Will run all the above, as well as removing sgfxi and svmi components"
	echo "${C}10 - $lastOption${S} - $lastOptionText"
	echo $LINE
	echo -e $SLE
	echo $LINE
	select opt in $options
	do
		case $opt in
			remove-backup-files)
				remove_data_files_check $opt
				repeat='true'
				;;
			remove-xorg.conf-backup-files)
				remove_data_files_check $opt
				repeat='true'
				;;
			remove-kernel-downloads)
				remove_data_files_check $opt
				repeat='true'
				;;
			remove-video-driver-downloads)
				remove_data_files_check $opt
				repeat='true'
				;;
			remove-virtual-machine-downloads)
				remove_data_files_check $opt
				repeat='true'
				;;
			remove-log-files)
				remove_data_files_check $opt
				repeat='true'
				;;
			remove-script-configuration-files)
				remove_data_files_check $opt
				repeat='true'
				;;
			uninstall-smxi)
				remove_data_files_check $opt
				echo $LINE
				echo "${S}Ok, ${C}$SCRIPT_NAME${S} is gone, thanks for checking it out!"
				echo "Exiting ${C}$SCRIPT_NAME${S} now since there are no pieces to operate the script any longer ;-)${N}"
				exit 0
				;;
			uninstall-all-smxi-scripts)
				remove_data_files_check $opt
				echo $LINE
				echo "${S}Ok, ${C}$SCRIPT_NAME${S}, ${C}sgfxi${S}, and ${C}svmi${S} are all gone, thanks for checking them out!"
				echo "Exiting ${C}$SCRIPT_NAME${S} now since there are no pieces to operate the script any longer ;-)${N}"
				exit 0
				;;
			$lastOption)	
				echo "${S}$lastOptionExit${N}"
				if [ "$1" == 'y-option' ];then
					exit 0
				fi
				;;
			*)	print_error 'opt'
				repeat='true'
				;;
		esac
		break
	done
	
	if [ "$repeat" == 'true' ];then
		clean_smxi_stuff
	fi
}

# args: $1 - which type to remove; $2 - no-question, just do it
remove_data_files_check()
{
	local repeat='' opt='' options='' removeType='-f'
	local backupFileList='/boot/grub/menu.lst-bu* /etc/apt/sources.list-bu* /etc/apt/sources.list.d/*.list-bu* /etc/kde3/kdm/kdmrc.bu* /etc/fstab.old  /usr/share/services/kded/mediamanager.desktop-bu*'
	local backupXorgFileList='/etc/X11/xorg.conf.1st* /etc/X11/xorg.conf-bu*'
	local configFileList="/etc/smxi.conf $SMDV $SMDL"
	local logFilesList="$CLEAN_X_ORG_LOG* $LOG_FILE* /var/log/sgfxi/sgfxi.log* /var/log/svmi.log*"

	local removeList='' removeFile='' extraText=''
	local removedSize=''
	local removedCount=''
	local videoDownloads='/usr/src/sgfxi-downloads'
	local vmDownloads='/usr/src/svmi-downloads'
	
	case $1 in
		remove-backup-files)
			for removeFile in $backupFileList
			do
				removeList="$removeList $( ls $removeFile 2>/dev/null )"
			done
			extraText='delete '
			;;
		remove-xorg.conf-backup-files)
			for removeFile in $backupXorgFileList
			do
				removeList="$removeList $( ls $removeFile 2>/dev/null )"
			done
			extraText='delete '
			;;
		remove-kernel-downloads)
			if [ -d $SM_KERNEL_DOWNLOAD_DIRECTORY ];then
				removeList=$SM_KERNEL_DOWNLOAD_DIRECTORY
				extraText='delete '
				removeType='-rf'
			fi
			;;
		remove-video-driver-downloads)
			if [ -d $videoDownloads ];then
				removeList=$videoDownloads
				extraText='delete '
				removeType='-rf'
			fi
			;;
		remove-virtual-machine-downloads)
			 if [ -d $vmDownloads ];then
			 	removeList=$vmDownloads
				extraText='delete '
				removeType='-rf'
			fi
			;;
		remove-log-files)
			for removeFile in $logFilesList
			do
				removeList="$removeList $( ls $removeFile 2>/dev/null )"
			done
			if [ -d /var/log/sgfxi ];then
				removeList="$removeList /var/log/sgfxi/"
			fi
			extraText='delete '
			removeType='-rf'
			;;
		remove-script-configuration-files)
			for removeFile in $configFileList
			do
				if [ -e $removeFile ];then
					removeList="$removeList $removeFile"
				fi
			done
			extraText='delete '
			;;
		uninstall-all-smxi-scripts)
			for removeFile in $REMOVE_LIST_SM $REMOVE_LIST_SV $REMOVE_LIST_SG
			do
				removeList="$removeList $( ls $SCRIPT_HOME/$removeFile 2>/dev/null )"
			done
			removeList="$removeList $( ls $SCRIPT_ROTATE* 2>/dev/null )"
			removeList="$removeList $( ls /etc/logrotate.d/sgfxi* 2>/dev/null )"
			removeList="$removeList $( ls /etc/logrotate.d/svmi* 2>/dev/null )"
			removeList="$removeList $( ls /etc/modprobe.d/kms-sg-blacklist.conf 2>/dev/null )"
			;;
		uninstall-smxi)
			for removeFile in $REMOVE_LIST_SM
			do
				removeList="$removeList $( ls $SCRIPT_HOME/$removeFile 2>/dev/null )"
			done
			removeList="$removeList $( ls $SCRIPT_ROTATE* 2>/dev/null )"
			;;
	esac
	# straighten the remove list 
	if [ -n "$removeList" ];then
		removeList=$( echo $removeList )
		removedCount="$( wc -w <<< $removeList )"
	fi
	# dump the data for full cleanup without interaction after first approval is given
	if [ "$2" == 'no-question' ];then
		if [ -n "$removeList" ];then
			echo "${S}Carrying out requested action: ${C}$1${S} now...${N}"
			rm $removeType $removeList
			echo "${C}$removedCount${S} Files/Directories removed.${N}"
		else
			echo "${M}There is no data to remove for requested action: ${C}$1${N}"
		fi
	else
		# need to be careful here since we don't want to do rm -rf
		if [ -z "$removeList" -o "$( wc -w <<< $removeList )" -eq 0 ];then
			echo $MLINE
			echo "${M}There is no data to remove for requested action: ${C}$1${N}"
			print_hec
		else
			echo $LINE
			echo "${S}Requested action: ${C}$1"
			echo $LINE
			if [ "$1" == 'uninstall-all-smxi-scripts' ];then
				echo -e "${Q}Are you sure you want to remove ${C}$SCRIPT_NAME${Q} as well as all of its associated files,"
				echo "directories, logs, configs, and data? Doing so will also remove all ${C}$MOD_GFX${Q} and ${C}$MOD_VM${Q} components."
			elif [ "$1" == 'uninstall-smxi' ];then
				echo -e "${Q}Are you sure you want to remove ${C}$SCRIPT_NAME${Q} as well as all of its associated files,"
				echo "directories, logs, configs, and data?${Q}."
			else
				echo -e "${Q}Are you sure you want to $extraText${C}$removedCount${Q} files/directories?"
				if [ "$1" != 'remove-xorg.conf-backup-files' ];then
					echo "${C}$removeList"
				fi
				echo $LINE
				echo "${S}Calculating free space created by removing this data...${N}"
				removedSize=$( du -ch $removeList 2>/dev/null | grep 'total' )
				removedSize=$( echo $removedSize )
				echo "${S}Removing this data will free up ${C}$removedSize${S} in your system${N}"
			fi
			echo $LINE
			echo "${C}1 - yes-delete-data${S} - Delete the data."
			echo "${C}2 - return-main-menu${S} - Go back to main menu, skip deletions."
			echo $LINE
			echo -e $SLE
			echo $LINE
			options="yes-delete-data return-main-menu"
			select opt in $options
			do
				case $opt in
					yes-delete-data)
						case $1 in
							uninstall-smxi)
								remove_data_files_check 'remove-backup-files' 'no-question'
								remove_data_files_check 'remove-kernel-downloads' 'no-question'
								remove_data_files_check 'remove-log-files' 'no-question'
								remove_data_files_check 'remove-script-configuration-files' 'no-question'
								;;
							uninstall-all-smxi-scripts)
								remove_data_files_check 'remove-backup-files' 'no-question'
								remove_data_files_check 'remove-xorg.conf-backup-files' 'no-question'
								remove_data_files_check 'remove-kernel-downloads' 'no-question'
								remove_data_files_check 'remove-video-driver-downloads' 'no-question'
								remove_data_files_check 'remove-virtual-machine-downloads' 'no-question'
								remove_data_files_check 'remove-log-files' 'no-question'
								remove_data_files_check 'remove-script-configuration-files' 'no-question'
								;;
						esac
						echo $LINE
						echo "${S}Carrying out requested action: ${C}$1${S}...${N}"
						rm $removeType $removeList
						echo "${C}$removedCount${S} Files/Directories removed.${N}"
						;;
					return-main-menu)	
						echo "${S}Continuing without deleting backup files.${N}"
						;;
					*)	print_error 'opt'
						repeat='true'
						;;
				esac
				break
			done
	
			if [ "$repeat" == 'true' ];then
				remove_data_files_check
			fi
		fi
	fi
}

###**EOF**###


syntax highlighted by Code2HTML, v. 0.9.1