620 lines
14 KiB
Bash
620 lines
14 KiB
Bash
#!/bin/bash
|
|
## Title : ACHAR - Auto Completion of Hosts Add/Remove script
|
|
## Version : 0.2.2
|
|
## GIT Repo : https://git.zaks.web.za/zaks-web/achar
|
|
## Author : Ze'ev Schurmann
|
|
## Company : ZAKS Web
|
|
## Website : https://www.zaks.web.za/
|
|
## Reddit : https://www.reddit.com/r/ZAKSWeb
|
|
## License : GPL3 or Later
|
|
## Description: This tool allows for the management of bash auto completion of
|
|
## hostnames when using SSH or RSync in Bash.
|
|
##
|
|
## USAGE
|
|
##
|
|
## From the bash terminal, type:
|
|
## $ achar {command} {context}
|
|
##
|
|
## COMMANDS
|
|
##
|
|
## add - adds a host to your list of common hosts
|
|
## $ achar add username@hostname.domainname.tld
|
|
## $ achar add username@1.2.3.4
|
|
##
|
|
## disable - disables auto completion of hostnames for current system user
|
|
## $ achar disable
|
|
## * does not delete the list of hosts stored at ~/.achar/hosts
|
|
##
|
|
## enable - enables auto completion of hostnames for current system user
|
|
## $ achar enable
|
|
##
|
|
## help - displays this block of text
|
|
## $ achar help
|
|
##
|
|
## license - displays the GPL3 and Later license
|
|
## $ achar license
|
|
##
|
|
## list - list all existing hosts from your list of common hosts
|
|
## $ achar list
|
|
## * You can use context to search for a specific hostname or part there of
|
|
## $ achar list username
|
|
## $ achar list part-of-hostname
|
|
##
|
|
## remove - removes an existing host from your list of common hosts
|
|
## $ achar remove username@hostname.domainname.tld
|
|
## $ achar remove username@1.2.3.4
|
|
##
|
|
## reset - deletes all saved hosts
|
|
## $ achar reset
|
|
##
|
|
## uninstall - uninstalls achar from your system
|
|
## $ sudo achar uninstall
|
|
## # achar uninstall
|
|
## * does not delete the list of hosts stored at ~/.achar/hosts
|
|
##
|
|
## update - checks for an update to ACHAR and prompts you to install it
|
|
## $ achar update
|
|
|
|
bashrc_array=("# enable host autocompletion for ssh and rsync" "[ -f ~/.achar/completions ] && [ -f ~/.achar/hosts ] && . ~/.achar/completions")
|
|
completions_array=("# Include existing rsync completions" ". /usr/share/bash-completion/completions/rsync" "" "# Include existing ssh completions" ". /usr/share/bash-completion/completions/ssh" "" "# Function to add custom user@hostname completions" "_custom_hosts()" "{" " local cur=\"\${COMP_WORDS[COMP_CWORD]}\"" " local hosts=\$(cat ~/.achar/hosts)" " COMPREPLY=( \$(compgen -W \"\$hosts\" -- \"\$cur\") )" "}" "" "# Function to handle extended rsync completions" "_extended_rsync_completions()" "{" " local cur=\"\${COMP_WORDS[COMP_CWORD]}\"" "" " # Use custom host completions if '@' is detected" " if [[ \"\$cur\" == *@* ]]; then" " _custom_hosts" " else" " # Fallback to default rsync completion" " _rsync" " fi" "}" "" "# Extend the existing ssh completion function to include custom hosts" "_extended_ssh_completions()" "{" " local cur=\"\${COMP_WORDS[COMP_CWORD]}\"" "" " # Use custom host completions if '@' is detected" " if [[ \"\$cur\" == *@* ]]; then" " _custom_hosts" " else" " # Fallback to default ssh completion" " _ssh" " fi" "}" "" "# Preserve the original rsync completion function" "if declare -F _rsync &>/dev/null; then" " complete -r rsync" " complete -F _extended_rsync_completions rsync" "fi" "" "# Preserve the original ssh completion function" "if declare -F _ssh &>/dev/null; then" " complete -r ssh" " complete -F _extended_ssh_completions ssh" "fi")
|
|
completions_md5="a148257d1f32705ef2c1f292e72d528c"
|
|
|
|
function achar_add {
|
|
|
|
local username_and_hostname
|
|
|
|
username_and_hostname=$1
|
|
validate_achar_installation hosts
|
|
validate_host "$username_and_hostname"
|
|
|
|
if [[ -z $(cat ~/.achar/hosts | grep "$username_and_hostname") ]]; then
|
|
|
|
echo $username_and_hostname >> ~/.achar/hosts
|
|
|
|
else
|
|
|
|
echo "$username_and_hostname is already added!" >&2
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function achar_disable {
|
|
|
|
validate_achar_installation disabled
|
|
|
|
rm ~/.achar/completions
|
|
|
|
for ((i=0; i<${#bashrc_array[@]}; i++)); do
|
|
|
|
line=$(echo "${bashrc_array[$i]}" | sed 's/[]\/$*.^|[]/\\&/g')
|
|
sed -i "/^$line$/d" ~/.bashrc
|
|
|
|
done
|
|
|
|
echo "Please start a new Bash Terminal Session for the change to take affect."
|
|
|
|
}
|
|
|
|
function achar_enable {
|
|
|
|
validate_achar_installation enabled
|
|
|
|
if [[ ! -d ~/.achar ]]; then
|
|
|
|
mkdir ~/.achar
|
|
|
|
fi
|
|
|
|
if [[ ! -f ~/.achar/hosts ]]; then
|
|
|
|
touch ~/.achar/hosts
|
|
|
|
fi
|
|
|
|
touch ~/.achar/completions
|
|
|
|
for ((i=0; i<${#completions_array[@]}; i++)); do
|
|
|
|
echo "${completions_array[$i]}" >> ~/.achar/completions
|
|
|
|
done
|
|
|
|
for ((i=0; i<${#bashrc_array[@]}; i++)); do
|
|
|
|
echo "${bashrc_array[$i]}" >> ~/.bashrc
|
|
|
|
done
|
|
|
|
echo "Please start a new Bash Terminal Session for the change to take affect."
|
|
|
|
}
|
|
|
|
function achar_help {
|
|
|
|
local script_path
|
|
|
|
script_path="${BASH_SOURCE[0]}"
|
|
echo
|
|
|
|
while read -r line; do
|
|
|
|
if [[ ${line:0:2} == "##" ]]; then
|
|
|
|
echo "${line:3}"
|
|
|
|
elif [[ ${line:0:2} == "#!" ]]; then
|
|
|
|
donothing=0
|
|
|
|
else
|
|
|
|
echo
|
|
exit 0
|
|
|
|
fi
|
|
|
|
done < "$script_path"
|
|
|
|
}
|
|
|
|
function achar_license {
|
|
|
|
echo
|
|
curl -s https://git.zaks.web.za/zaks-web/achar/raw/branch/main/LICENSE | fmt
|
|
|
|
if [[ $? != 0 ]]; then
|
|
|
|
echo "Could not get the license file." >&2
|
|
echo "Either you are not connected to the Internet or the update server is down." >&2
|
|
exit 1
|
|
|
|
fi
|
|
|
|
echo
|
|
|
|
}
|
|
|
|
function achar_list {
|
|
|
|
validate_achar_installation hosts
|
|
|
|
if [[ -z $1 ]]; then
|
|
|
|
cat ~/.achar/hosts | sort
|
|
|
|
else
|
|
|
|
cat ~/.achar/hosts | grep "$1" | sort
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function achar_remove {
|
|
|
|
local username_and_hostname
|
|
|
|
username_and_hostname=$1
|
|
validate_achar_installation hosts
|
|
validate_host $username_and_hostname
|
|
|
|
if [[ -z $(cat ~/.achar/hosts | grep "$username_and_hostname") ]]; then
|
|
|
|
echo "$username_and_hostname is not there!" >&2
|
|
exit 1
|
|
|
|
else
|
|
|
|
sed -i "/^$username_and_hostname$/d" ~/.achar/hosts
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function achar_reset {
|
|
|
|
validate_achar_installation hosts
|
|
echo "This will delete all saved hosts and"
|
|
echo "and start from scratch."
|
|
echo
|
|
echo "Press ENTER to continue or CTRL+C to STOP!"
|
|
read text
|
|
rm ~/.achar/hosts
|
|
touch ~/.achar/hosts
|
|
|
|
}
|
|
|
|
function achar_uninstall {
|
|
|
|
local script_path
|
|
local text
|
|
|
|
script_path="${BASH_SOURCE[0]}"
|
|
|
|
if [[ $(whoami) == "root" ]]; then
|
|
|
|
echo "You are about to uninstall ACHAR."
|
|
echo
|
|
echo "If you want to disable the autocompletions, then"
|
|
echo "you must run \"achar disable\" for each user."
|
|
echo "This is recommended if you are planning to install"
|
|
echo "a new version."
|
|
echo
|
|
echo "Press ENTER to continue or CTRL+C to STOP!"
|
|
read text
|
|
rm $script_path
|
|
|
|
else
|
|
|
|
echo "Please run with root privilages (sudo) in order to uninstall."
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function achar_update {
|
|
|
|
local difference
|
|
local script_path
|
|
local stable_version_number
|
|
local -a stable_version_number_array
|
|
local test_stable
|
|
local test_version
|
|
local update_available
|
|
local -a version_line
|
|
local version_number
|
|
local -a version_number_array
|
|
|
|
script_path="${BASH_SOURCE[0]}"
|
|
version_line=($(grep '^## Version' "$script_path"))
|
|
version_number=${version_line[3]}
|
|
stable_version_number=$(curl -s https://git.zaks.web.za/zaks-web/achar/raw/branch/main/stable_version)
|
|
|
|
if [[ $? != 0 ]]; then
|
|
echo "Could not check for latest version." >&2
|
|
echo "Either you are not connected to the Internet or the update server is down." >&2
|
|
exit 1
|
|
fi
|
|
|
|
oldIFS=$IFS
|
|
IFS="."
|
|
version_number_array=($version_number)
|
|
stable_version_number_array=($stable_version_number)
|
|
IFS=$oldIFS
|
|
|
|
if [[ ${#version_number_array[@]} -gt ${#stable_version_number_array[@]} ]]; then
|
|
|
|
difference=$((${#version_number_array[@]}-${#stable_version_number_array[@]}))
|
|
|
|
for ((i=0; i<$differnce; i++)); do
|
|
|
|
$stable_version_number_array[${#stable_version_number_array[@]}]=0
|
|
|
|
done
|
|
|
|
elif [[ ${#stable_version_number_array[@]} -gt ${#version_number_array[@]} ]]; then
|
|
|
|
difference=$((${#version_number_array[@]}-${#stable_version_number_array[@]}))
|
|
|
|
for ((i=0; i<$differnce; i++)); do
|
|
|
|
$stable_version_number_array[${#stable_version_number_array[@]}]=0
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
echo "Current version is $version_number"
|
|
echo "Latest version is $stable_version_number"
|
|
update_available="false"
|
|
|
|
for ((i=0; i<${#version_number_array[@]}; i++)); do
|
|
|
|
if [[ $update_available == "false" ]]; then
|
|
|
|
test_stable=${stable_version_number_array[$i]##+(0)}
|
|
test_version=${version_number_array[$i]##+(0)}
|
|
|
|
if [[ -z $test_stable ]]; then
|
|
|
|
test_stable=0
|
|
|
|
fi
|
|
|
|
if [[ -z $test_version ]]; then
|
|
|
|
test_version=0
|
|
|
|
fi
|
|
|
|
if [[ ${#stable_version_number_array[@]} -gt ${#version_number_array[@]} ]]; then
|
|
|
|
update_available="true"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if [[ $update_available == "true" ]]; then
|
|
|
|
echo "Update is avaiable!"
|
|
echo
|
|
echo "First run \"achar disable\" for all users."
|
|
echo "Then run \"achar uninstall\" as root or sudo."
|
|
echo "Lastly, follow the instructions at"
|
|
echo "https://git.zaks.web.za/zaks-web/achar"
|
|
echo "to install the latest version."
|
|
|
|
else
|
|
|
|
echo "You currently have the latest version!"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function validate_achar_installation {
|
|
|
|
local achar_installation_error_code=""
|
|
local what_test
|
|
what_test=$1
|
|
|
|
if [[ -d ~/.achar ]]; then
|
|
|
|
achar_installation_error_code="A$achar_installation_error_code"
|
|
|
|
else
|
|
|
|
achar_installation_error_code="a$achar_installation_error_code"
|
|
|
|
fi
|
|
|
|
if [[ -f ~/.achar/hosts ]]; then
|
|
|
|
achar_installation_error_code="H$achar_installation_error_code"
|
|
|
|
else
|
|
|
|
achar_installation_error_code="h$achar_installation_error_code"
|
|
|
|
fi
|
|
|
|
if [[ -f ~/.achar/completions ]]; then
|
|
|
|
md5_test=$(cat ~/.achar/completions | md5sum)
|
|
|
|
if [[ ${md5_test:0:32} == $completions_md5 ]]; then
|
|
|
|
achar_installation_error_code="C$achar_installation_error_code"
|
|
|
|
else
|
|
|
|
echo "File corrupt: ~/.achar/completions" >&2
|
|
exit 1
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
achar_installation_error_code="c$achar_installation_error_code"
|
|
|
|
fi
|
|
|
|
test=$(echo "${bashrc_array[1]}" | sed 's/[]\/$*.^|[]/\\&/g')
|
|
|
|
if [[ -z $(cat ~/.bashrc | grep "${bashrc_array[0]}") ]] || [[ -z $(cat ~/.bashrc | grep "$test") ]]; then
|
|
|
|
achar_installation_error_code="b$achar_installation_error_code"
|
|
|
|
else
|
|
|
|
achar_installation_error_code="B$achar_installation_error_code"
|
|
|
|
fi
|
|
|
|
if [[ $achar_installation_error_code == "BCHA" ]] && [[ $what_test == "enabled" ]]; then
|
|
|
|
echo "ACHAR is already enabled!"
|
|
exit 1
|
|
|
|
elif [[ $achar_installation_error_code == "bcha" ]] && [[ $what_test == "disabled" ]]; then
|
|
|
|
echo "ACHAR is already disabled!"
|
|
exit 1
|
|
|
|
elif [[ $achar_installation_error_code == "bcHA" ]] && [[ $what_test == "disabled" ]]; then
|
|
|
|
echo "ACHAR is already disabled!"
|
|
exit 1
|
|
|
|
elif [[ $achar_installation_error_code == "bcha" ]] && [[ -z $what_test ]]; then
|
|
|
|
echo "ACHAR is disabled!"
|
|
exit 1
|
|
|
|
elif [[ $achar_installation_error_code == "bcha" ]] && [[ $what_test == "hosts" ]]; then
|
|
|
|
echo "ACHAR is disabled!"
|
|
exit 1
|
|
|
|
elif [[ $achar_installation_error_code != "BCHA" ]] && [[ $achar_installation_error_code != "bcha" ]] && [[ -z $what_test ]]; then
|
|
|
|
echo "Something is wrong with your setup!" >&2
|
|
|
|
if [[ ${achar_installation_error_code:0:1} == "b" ]]; then
|
|
|
|
echo "Required code missing from ~/.bashrc" >&2
|
|
|
|
fi
|
|
|
|
if [[ ${achar_installation_error_code:1:1} == "c" ]]; then
|
|
|
|
echo "File missing: ~/.achar/completions" >&2
|
|
|
|
fi
|
|
|
|
if [[ ${achar_installation_error_code:2:1} == "h" ]]; then
|
|
|
|
echo "File missing: ~/.achar/hosts" >&2
|
|
|
|
fi
|
|
|
|
if [[ ${achar_installation_error_code:3:1} == "a" ]]; then
|
|
|
|
echo "Folder missing: ~/.achar/" >&2
|
|
|
|
fi
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function validate_host {
|
|
|
|
local hostname
|
|
local -a temp_array
|
|
local username_and_hostname
|
|
local username
|
|
|
|
if [[ -z $1 ]]; then
|
|
|
|
echo "Unexpected Error!"
|
|
exit 1
|
|
|
|
fi
|
|
|
|
username_and_hostname="$1"
|
|
temp_array=($username_and_hostname)
|
|
|
|
if [[ ${#temp_array[@]} != 1 ]]; then
|
|
|
|
echo "Invalid Hostname!"
|
|
exit 1
|
|
|
|
fi
|
|
|
|
old_ifs=$IFS
|
|
IFS="@"
|
|
temp_array=($username_and_hostname)
|
|
IFS=$old_ifs
|
|
|
|
if [[ ${#temp_array[@]} != 2 ]]; then
|
|
|
|
echo "Invalid Hostname!"
|
|
exit 1
|
|
|
|
fi
|
|
|
|
username=${temp_array[0]}
|
|
hostname=${temp_array[1]}
|
|
|
|
if [[ $hostname =~ ^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]]; then
|
|
|
|
donothing=0
|
|
|
|
elif nslookup "$hostname" > /dev/null 2>&1; then
|
|
|
|
donothing=0
|
|
|
|
else
|
|
|
|
echo "Invalid Domain Name or IP address!"
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [[ ${username:0:1} =~ ^[0-9]$ ]] || [[ ! $username =~ ^[A-Za-z0-9_.-]+$ ]]; then
|
|
|
|
echo "Username is not a valid format!"
|
|
echo "Must contain \"A-Z\", \"a-z\", \"0-9\", \"_\", \".\" and \"-\"."
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
if [[ -z $1 ]]; then
|
|
|
|
achar_help
|
|
|
|
elif [[ ${1,,} == "add" ]]; then
|
|
|
|
if [[ -z $2 ]]; then
|
|
|
|
echo "Please include a username@hostname" >&2
|
|
exit 1
|
|
|
|
else
|
|
|
|
achar_add $2
|
|
|
|
fi
|
|
|
|
elif [[ ${1,,} == "disable" ]]; then
|
|
|
|
achar_disable
|
|
|
|
elif [[ ${1,,} == "enable" ]]; then
|
|
|
|
achar_enable
|
|
|
|
elif [[ ${1,,} == "help" ]]; then
|
|
|
|
achar_help
|
|
|
|
elif [[ ${1,,} == "license" ]]; then
|
|
|
|
achar_license
|
|
|
|
elif [[ ${1,,} == "list" ]]; then
|
|
|
|
if [[ -z $2 ]]; then
|
|
|
|
achar_list
|
|
|
|
else
|
|
|
|
achar_list $2
|
|
|
|
fi
|
|
|
|
elif [[ ${1,,} == "remove" ]]; then
|
|
|
|
if [[ -z $2 ]]; then
|
|
|
|
echo "Please include a username@hostname" >&2
|
|
exit 1
|
|
|
|
else
|
|
|
|
achar_remove $2
|
|
|
|
fi
|
|
|
|
elif [[ ${1,,} == "reset" ]]; then
|
|
|
|
achar_reset
|
|
|
|
elif [[ ${1,,} == "uninstall" ]]; then
|
|
|
|
achar_uninstall
|
|
|
|
elif [[ ${1,,} == "update" ]]; then
|
|
|
|
achar_update
|
|
|
|
else
|
|
|
|
achar_help
|
|
|
|
fi
|
|
|
|
exit 0
|