#!/bin/bash
#
# Takipi installation script - this script runs as a part of the installation system. It only sets the
# JAVA_TOOL_OPTIONS environment variable so all the options to run a java system would get "attached" by our agent.
#

declare -r INIT_FUNCTIONS_PATH=/lib/lsb/init-functions
declare -r INIT_FUNCTIONS_PATH1=/etc/init.d/functions
declare -r INIT_FUNCTIONS_PATH2=/etc/rc.d/init.d/functions
declare -r INIT_FUNCTIONS_PATH3=/etc/init.d/functions.sh

declare -r TAKIPI_PROFILE_SCRIPT_DIR=/etc/profile.d/
declare -r TAKIPI_PROFILE_SCRIPT=$TAKIPI_PROFILE_SCRIPT_DIR"takipi_profile.sh" #/etc/profile.d/takipi_profile.sh

declare -r ENVIRONMENT_FILE=/etc/environment
declare -r TAKIPI_AGENT_LIB_NAME=TakipiAgent
declare    USE_ED=0

# append string to file
# $1 - the string to append
# $2 - the path to the file
function append_string()
{
	echo "$1" >> "$2"
}

# remove string from file (the string is assumed not to include any @ chars)
# $1 - the string to remove
# $2 - the path to the file
function remove_string()
{
	if [ $USE_ED -eq 1 ]; then
		REGEX_STRING=${1//\//\\\\\/}
		printf ",g/^$REGEX_STRING/d\nw\nq\n" | ed "$2" -s
	elif [ $USE_ED -eq 2 ]; then
		sed "\@^$1@d" $2 > $2~
		mv $2~ $2
	fi
}

# appends a string but removes all its appearences first (the string is assumed not to include any @ chars)
# $1 - the string to append
# $2 - the path to the file
function append_if_missing()
{
	remove_string "$1" "$2"
	append_string "$1" "$2"
}

# patch the init-functions file
# $1 - the path to the init-functions file
function patch_init_functions_file()
{
	append_if_missing "JAVA_TOOL_OPTIONS=-agentlib:$TAKIPI_AGENT_LIB_NAME # Takipi installation addition" "$1"
	append_if_missing "export JAVA_TOOL_OPTIONS # Takipi installation addition" "$1"
}

# unpatch the init-functions file
# $1 - the path to the init-functions file
function unpatch_init_functions_file()
{
	remove_string "JAVA_TOOL_OPTIONS=-agentpath:$AGENT_PATH # Takipi installation addition" "$1"
	remove_string "JAVA_TOOL_OPTIONS=-agentlib:$TAKIPI_AGENT_LIB_NAME # Takipi installation addition" "$1"
	remove_string "export JAVA_TOOL_OPTIONS # Takipi installation addition" "$1"
}

# creates the profile script
# $1 - the profile script file path
function create_profile_script()
{
	(
	echo "#!/bin/bash";
	echo "# This file is auto-generated by the Takipi installation system";
	echo "";
	echo "AGENT_PATH=-agentlib:$TAKIPI_AGENT_LIB_NAME";
	echo "";
	echo "if [[ \"\$JAVA_TOOL_OPTIONS\" != *\"\$AGENT_PATH\"* ]]; then";
	echo "	JAVA_TOOL_OPTIONS=\"\$JAVA_TOOL_OPTIONS \$AGENT_PATH\"";
	echo "	export JAVA_TOOL_OPTIONS";
	echo "fi";
	) > $1
}

# patch the environment file
# $1 - the path to the environment file
function patch_environment_file()
{
	TEMP_ENV_FILE=$(mktemp)
	
	REGEX_AGENT_LIB=${TAKIPI_AGENT_LIB_NAME//\//\\\/}
	
	awk '\
	BEGIN { found = 0; }\
	{ \
		if (index($0, "JAVA_TOOL_OPTIONS=") == 1)\
		{\
			gsub(/"-agentlib:'$REGEX_AGENT_LIB'"/,"", $0); \
			print $0 " \"-agentlib:'$TAKIPI_AGENT_LIB_NAME'\"";\
			found = 1;\
		}\
		else\
		{\
			print $0;\
		}\
	} \
	END {\
		if (found != 1)\
		{\
			print "JAVA_TOOL_OPTIONS=\"-agentlib:'$TAKIPI_AGENT_LIB_NAME'\"";\
		}\
	}' $1 > TEMP_ENV_FILE

	mv -f TEMP_ENV_FILE $1
}

# unpatch the environment file
# $1 - the path to the environment file
function unpatch_environment_file()
{
	TEMP_ENV_FILE=$(mktemp)
	
	REGEX_AGENT_PATH=${AGENT_PATH//\//\\\/}
	REGEX_AGENT_LIB=${TAKIPI_AGENT_LIB_NAME//\//\\\/}
	
	awk '\
	BEGIN {}\
	{ \
		if (index($0, "JAVA_TOOL_OPTIONS") == 1)\
		{\
			gsub(/"\-agentpath:'$REGEX_AGENT_PATH'"/,"", $0); \
			gsub(/"-agentlib:'$REGEX_AGENT_LIB'"/,"", $0); \
			gsub(/"JAVA_TOOL_OPTIONS="/,"", $0); \
			if ($0 !~ /^JAVA_TOOL_OPTIONS=[ \t\r\n]*$/) \
			{\
				print $0;\
			}\
		}\
		else\
		{\
			print $0;\
		}\
	} \
	END {}' $1 > TEMP_ENV_FILE

	mv -f TEMP_ENV_FILE $1
}

# patch the sudoers file
# no need the path to the sudoers file because the visudo knows the path by itself
function patch_sudoers_file()
{
	type -p visudo > /dev/null
	
	if [ $? -ne 0 ]; then
		if [ -f /usr/sbin/visudo ]; then
			VISUDO_PATH=/usr/sbin/visudo
		else
			return 1
		fi
	else
		VISUDO_PATH=visudo
	fi

	PATCH_SUDOERS_SCRIPT=$(mktemp)
	
	(
		echo "#!/bin/bash";
		echo "# This file is auto-generated by the Takipi installation system";
		echo "";
		echo "if [ ! -z \"\$1\" ]; then";
		echo "	output_file="
		echo "	for param in \"\$@\"; do"
		echo "		if [ -f \$param ]; then"
		echo "			output_file=\$param"
		echo "			break"
		echo "		fi"
		echo "	done"
		echo "	if [ -f \"\$output_file\" ]; then"
		
		if [ $USE_ED -eq 1 ]; then
			echo "		printf \",g/^Defaults	env_keep+=JAVA_TOOL_OPTIONS # added by Takipi installation/d\\nw\\nq\\n\" | ed \$output_file --silent";
		elif [ $USE_ED -eq 2 ]; then
			echo "		sed \"\\@^Defaults	env_keep+=JAVA_TOOL_OPTIONS # added by Takipi installation@d\" \$output_file > \$output_file.tmp.~";
			echo "		mv \$output_file.tmp.~ \$output_file";
		fi
		
		echo "		echo \"Defaults	env_keep+=JAVA_TOOL_OPTIONS # added by Takipi installation\" >> \$output_file";
		echo "	fi"
		echo "else";
		echo "	export EDITOR=\$0";
		echo "	$VISUDO_PATH 1>/dev/null 2>&1";
		echo "fi";
	) >  "$PATCH_SUDOERS_SCRIPT"
	
	chmod +x "$PATCH_SUDOERS_SCRIPT"
	sh "$PATCH_SUDOERS_SCRIPT"

	rm -f "$PATCH_SUDOERS_SCRIPT"
}

# patch the sudoers file
# no need the path to the sudoers file because the visudo knows the path by itself
function unpatch_sudoers_file()
{
	type -p visudo > /dev/null
	
	if [ $? -ne 0 ]; then
		if [ -f /usr/sbin/visudo ]; then
			VISUDO_PATH=/usr/sbin/visudo
		else
			return 1
		fi
	else
		VISUDO_PATH=visudo
	fi
	
	UNPATCH_SUDOERS_SCRIPT=$(mktemp)
	
	(
		echo "#!/bin/bash";
		echo "# This file is auto-generated by the Takipi installation system";
		echo "";
		echo "if [ ! -z \"\$1\" ]; then";
		echo "	output_file="
		echo "	for param in \"\$@\"; do"
		echo "		if [ -f \$param ]; then"
		echo "			output_file=\$param"
		echo "			break"
		echo "		fi"
		echo "	done"
		echo "	if [ -f \"\$output_file\" ]; then"
		
		if [ $USE_ED -eq 1 ]; then
			echo "		printf \",g/^Defaults	env_keep+=JAVA_TOOL_OPTIONS # added by Takipi installation/d\\nw\\nq\\n\" | ed \$output_file --silent";
		elif [ $USE_ED -eq 2 ]; then
			echo "		sed \"\\@^Defaults	env_keep+=JAVA_TOOL_OPTIONS # added by Takipi installation@d\" \$output_file > \$output_file.tmp.~";
			echo "		mv \$1.tmp.~ \$1";
		fi
		
		echo "	fi"
		echo "else";
		echo "	export EDITOR=\$0";
		echo "	$VISUDO_PATH 1>/dev/null 2>&1";
		echo "fi";
	) >  "$UNPATCH_SUDOERS_SCRIPT"
	
	chmod +x "$UNPATCH_SUDOERS_SCRIPT"
	sh "$UNPATCH_SUDOERS_SCRIPT"

	rm -f "$UNPATCH_SUDOERS_SCRIPT"
}

# finds out which editor to use and sets USE_ED env var appropriately
# ed exists 	->	USE_ED = 1
# sed exists 	->	USE_ED = 2
# none exists	->	USE_ED = 0
function find_editor_to_use()
{
	type -p ed > /dev/null
	
	if [ $? -ne 0 ]; then
		type -p sed > /dev/null
		
		if [ $? -eq 0 ]; then
			USE_ED=2
		else
			USE_ED=0
		fi
	else
		USE_ED=1
	fi
}

# installs takipi environment variable
function install_takipi_env()
{
	# find which editor to use - if no editor, than don't try to install in the functions files
	# and in the sudoers files
	find_editor_to_use
	
	if [ $USE_ED -ne 0 ]; then
		# append the env var to the init-functions file
		if [ -f "$INIT_FUNCTIONS_PATH" ]; then
			patch_init_functions_file "$INIT_FUNCTIONS_PATH"
		fi

		if [ -f "$INIT_FUNCTIONS_PATH1" ]; then
			patch_init_functions_file "$INIT_FUNCTIONS_PATH1"
		fi

		if [ -f "$INIT_FUNCTIONS_PATH2" ]; then
			patch_init_functions_file "$INIT_FUNCTIONS_PATH2"
		fi

		if [ -f "$INIT_FUNCTIONS_PATH3" ]; then
			patch_init_functions_file "$INIT_FUNCTIONS_PATH3"
		fi
	fi

	# create the profile script - in some environments, the script would not run and
	# thus we set ourselves inside the /etc/environemnt file
	if [ -d "$TAKIPI_PROFILE_SCRIPT_DIR" ]; then
		if [ -f "$TAKIPI_PROFILE_SCRIPT" ]; then
			rm -f "$TAKIPI_PROFILE_SCRIPT"
		fi
		
		create_profile_script "$TAKIPI_PROFILE_SCRIPT"
	fi

	# append the env var to the environment file
	if [ -f "$ENVIRONMENT_FILE" ]; then
		patch_environment_file "$ENVIRONMENT_FILE"
	fi

	if [ $USE_ED -ne 0 ]; then
		# run the sudoers file patching
		patch_sudoers_file
	fi
}

# uninstall takipi environment variable
function uninstall_takipi_env()
{
	# find which editor to use - if no editor, than don't try to uninstall in the functions files
	# and in the sudoers files
	find_editor_to_use
	
	if [ $USE_ED -ne 0 ]; then
	# remove the env var from the init-functions file
		if [ -f "$INIT_FUNCTIONS_PATH" ]; then
			unpatch_init_functions_file "$INIT_FUNCTIONS_PATH"
		fi

		if [ -f "$INIT_FUNCTIONS_PATH1" ]; then
			unpatch_init_functions_file "$INIT_FUNCTIONS_PATH1"
		fi

		if [ -f "$INIT_FUNCTIONS_PATH2" ]; then
			unpatch_init_functions_file "$INIT_FUNCTIONS_PATH2"
		fi

		if [ -f "$INIT_FUNCTIONS_PATH3" ]; then
			unpatch_init_functions_file "$INIT_FUNCTIONS_PATH3"
		fi
	fi

	# remove the profile script
	if [ -f "$TAKIPI_PROFILE_SCRIPT" ]; then
		rm -f "$TAKIPI_PROFILE_SCRIPT"
	fi

	# append the env var to the environment file
	if [ -f "$ENVIRONMENT_FILE" ]; then
		unpatch_environment_file "$ENVIRONMENT_FILE"
	fi

	if [ $USE_ED -ne 0 ]; then
		# run the sudoers file unpatching
		unpatch_sudoers_file
	fi
}

# the main entry point of the program
# $1 - the type of installation - "install/uninstall"
# $2 - the path to the agent's so file
function main()
{
	AGENT_PATH=$2

	# check that we are running with root privileges
	if [ `id -u` -ne 0 ]; then
		echo "You need root privileges to run this script."
		exit 1
	fi

	case "$1" in
		install)
			install_takipi_env
			;;
		uninstall)
			uninstall_takipi_env
			;;
		*)
			echo $"Usage: $0 {install|uninstall} {Agent's path}"
			exit 1
	esac
}

main $@