dotfiles/.bashrc

236 lines
8.3 KiB
Bash

# Functions.
_agent_prompt_command() {
hash ssh-add >/dev/null 2>&1 && {
local SOCK
declare -g _SSH_PROMPT_ERROR_ISSUED
# Check the ssh agent socket is still alive.
ssh-add -l >/dev/null 2>&1
if (($? >= 2)); then
# Auth socket has become unusable, search for a new one.
SOCK="$(_find_agent_sock)"
if ((${PIPESTATUS[0]} == 0)); then
export SSH_AUTH_SOCK="$SOCK"
_SSH_PROMPT_ERROR_ISSUED=0
echo "Connected to alternate ssh-agent - you may need to re-add keys."
else
if [[ -z "$(egrep -v '^$' ~/.ssh/agents)" ]]; then
((${_SSH_PROMPT_ERROR_ISSUED:-0} == 0)) && {
echo "$(tput setaf 1 || tput AF 1)Lost connection to ssh-agent - no alternate available!$(tput op)"
unset SSH_AUTH_SOCK
_SSH_PROMPT_ERROR_ISSUED=1
}
else
((${_SSH_PROMPT_ERROR_ISSUED:-0} == 0)) && {
echo "$(tput setaf 1 || tput AF 1)Lost connection to ssh-agent - failed to connect to new agent!$(tput op)"
unset SSH_AUTH_SOCK
_SSH_PROMPT_ERROR_ISSUED=1
}
fi
fi
else
_SSH_PROMPT_ERROR_ISSUED=0
fi
unset SOCK
}
}
_clean_agent_socks() {
local I SSH_AUTH_SOCK
# Go through the array of sockets and validate each one.
for ((I = 0; I < ${#SOCKS[@]}; I++)); do
SSH_AUTH_SOCK="${SOCKS[$I]}" ssh-add -l >/dev/null 2>&1
(($? >= 2)) && {
unset SOCKS[$I]
}
done
}
_find_agent_sock() {
local I IFS=$'\n' REPLY SOCKS=() SSH_AUTH_SOCK="$SSH_AUTH_SOCK"
# Load the array of sockets, minus the one we know is unusable.
if ((${BASH_VERSINFO[0]} >= 4)); then
mapfile -t SOCKS < <(egrep -v "^$SSH_AUTH_SOCK\$" ~/.ssh/agents 2>/dev/null)
else
while read -r; do
SOCKS+=("$REPLY")
done < <(egrep -v "^$SSH_AUTH_SOCK\$" ~/.ssh/agents 2>/dev/null)
fi
# Search backwards through the list to find an active socket.
for ((I = (${#SOCKS[@]} - 1); I >= 0; I--)); do
SSH_AUTH_SOCK="${SOCKS[$I]}" ssh-add -l >/dev/null 2>&1
(($? <= 1)) && [[ ! -z "${SOCKS[$I]}" ]] && {
printf "%s" "${SOCKS[$I]}"
return 0
}
done
return 1
}
_lock_agents_file() {
local I
# Lock the ~/.ssh/agents file.
if [[ "$_PLATFORM" == "Linux" ]]; then
# Linux has 'flock', thankfully.
if exec 9>~/.ssh/agents.lock && flock -E 10 -w 0.5 9; then
return 0
else
echo "$(tput setaf 1 || tput AF 1)Failed to obtain lockfile!$(tput op)"
fi
elif [[ "$_PLATFORM" == "Darwin" ]]; then
# Do locking the sucky way on OSX.
for ((I=0; I < 5; I++)); do
if shlock -f "/tmp/agents.lock.$$" -p "$$"; then
return 0
else
sleep 0.1
fi
done
[[ "${_GOT_LOCK:-0}" == "0" ]] && echo "$(tput setaf 1 || tput AF 1)Failed to obtain lockfile!$(tput op)"
else
echo "$(tput setaf 1 || tput AF 1)File locking unsupported - skipping update of agents file!$(tput op)"
fi
return 1
}
_pop_agent_sock() {
local I IFS=$'\n' REPLY SOCKS=()
# Read the current list of auth sockets.
if ((${BASH_VERSINFO[0]} >= 4)); then
mapfile -t SOCKS <~/.ssh/agents
else
while read -r; do
SOCKS+=("$REPLY")
done <~/.ssh/agents
fi
# Remove the last instance of the socket in $SSH_AUTH_SOCK.
for ((I = (${#SOCKS[@]} - 1); I >= 0; I--)); do
[[ "${SOCKS[$I]}" == "$SSH_AUTH_SOCK" ]] && {
unset SOCKS[$I]
break
}
done
# Clean up any dead sockets - this modifies the SOCKS array.
_clean_agent_socks
# Write the new list back to disk.
printf "%s\n" "${SOCKS[@]}" >~/.ssh/agents
return $?
}
_push_agent_sock() {
local IFS=$'\n' REPLY SOCKS=()
# Read the current list of auth sockets.
if ((${BASH_VERSINFO[0]} >= 4)); then
mapfile -t SOCKS <~/.ssh/agents
else
while read -r; do
SOCKS+=("$REPLY")
done <~/.ssh/agents
fi
# Clean up any dead sockets - this modifies the SOCKS array.
_clean_agent_socks
# Write the new list back to disk.
printf "%s\n" "${SOCKS[@]}" "$SSH_AUTH_SOCK" >~/.ssh/agents
return $?
}
_unlock_agents_file() {
# Unlock the ~/.ssh/agents file.
if [[ "$_PLATFORM" == "Linux" ]]; then
exec 9>&-
elif [[ "$_PLATFORM" == "Darwin" ]]; then
rm -f "/tmp/agents.lock.$$"
fi
}
# Make bash a little more pleasent - these are valid for all versions.
shopt -s cdspell checkhash checkwinsize cmdhist histappend no_empty_cmd_completion
# Exit the shell on a Ctl+D.
IGNOREEOF=0
# History control.
HISTCONTROL="ignoredups"
HISTFILESIZE=100000
HISTIGNORE="w:bg:bg *:fg:fg *:jobs:exit:pwd:clear:history"
HISTSIZE=-1
HISTTIMEFORMAT="%d/%m/%y %H:%M:%S "
history -r
# Determine the colour of the username in the prompt.
if (( $(id -u) == 0 )); then
_COLOUR=1 # Red
else
_COLOUR=2 # Green
fi
# Version specific set up.
if (( ${BASH_VERSINFO[0]} >= 4 )); then
# Add to the shopts.
shopt -s checkjobs dirspell
# Set the prompts.
PROMPT_DIRTRIM=2
# No colour:
# PS1="[\u@\h] \w ->"
# Coloured username:
# PS1="[\[$(tput bold)$(tput setaf $_COLOUR)\]\u\[$(tput sgr0)\]@\h] \w ->"
# Coloured username + host:
# PS1="[\[$(tput bold)$(tput setaf $_COLOUR)\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \w ->"
# Coloured username + host + directory:
PS1="[\[$(tput bold)$(tput setaf $_COLOUR)\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \[$(tput bold)$(tput setaf 4)\]\w\[$(tput sgr0)\] ->"
else
# Set the prompts.
# No colour:
# PS1="[\u@\h] \$(echo \"\${PWD/#\$HOME/~}\" | awk -F/ '{if (NF>3) {printf \".../\" \$(NF-1) \"/\" \$NF} else {printf \$0}}') ->"
# Coloured username:
# PS1="[\[$(tput bold)$(tput setaf $_COLOUR)\]\u\[$(tput sgr0)\]@\h] \$(echo \"\${PWD/#\$HOME/~}\" | awk -F/ '{if (NF>3) {printf \".../\" \$(NF-1) \"/\" \$NF} else {printf \$0}}') ->"
# Coloured username + host:
# PS1="[\[$(tput bold)$(tput setaf $_COLOUR)\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \$(echo \"\${PWD/#\$HOME/~}\" | awk -F/ '{if (NF>3) {printf \".../\" \$(NF-1) \"/\" \$NF} else {printf \$0}}') ->"
# Coloured username + host + directory:
PS1="[\[$(tput bold)$(tput setaf $_COLOUR)\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \[$(tput bold)$(tput setaf 4)\]\$(echo \"\${PWD/#\$HOME/~}\" | awk -F/ '{if (NF>3) {printf \".../\" \$(NF-1) \"/\" \$NF} else {printf \$0}}')\[$(tput sgr0)\] ->"
fi
unset _COLOUR
# Set the debugger prompt.
# PS4="+(\\\$? = \$?) \${BASH_SOURCE##*/}\${FUNCNAME:+(\$FUNCNAME)}:\$LINENO: "
PS4="+(\[\e[33m\]\\\$? = \$?\[$(tput sgr0)\]) \[$(tput bold)$(tput setaf 4)\]\${BASH_SOURCE##*/}\[$(tput sgr0)\]\${FUNCNAME:+(\[$(tput bold)$(tput setaf 2)\]\$FUNCNAME\[$(tput sgr0)\])}:\[$(tput bold)$(tput setaf 1)\]\$LINENO\[$(tput sgr0)\]: "
# The commands to execute before the prompt is displayed.
PROMPT_COMMAND="_agent_prompt_command"
# Platform specific set up.
_PLATFORM="$(uname -s)"
if [[ "$_PLATFORM" = "Linux" ]]; then
# Linux specific aliases.
hash ftpwho >/dev/null 2>&1 && alias ftpwho='ftpwho -v'
hash iftop >/dev/null 2>&1 && alias iftop='TERM=vt100 iftop'
hash last less >/dev/null 2>&1 && alias laston='last -a | less'
hash ls >/dev/null 2>&1 && alias ls='ls -bFv --color=auto'
hash minicom >/dev/null 2>&1 && alias minicom='minicom -m -c on'
hash mkpasswd >/dev/null 2>&1 && alias pwgen='mkpasswd -m sha512crypt'
hash pine >/dev/null 2>&1 && alias pine='pine -p "{mail.open-source.co.uk/Service=IMAP/User=darren@afterdark.org.uk/TLS/NoValidate-Cert/NoRsh}.pinerc"'
hash pinfo >/dev/null 2>&1 && alias info='pinfo'
hash ping >/dev/null 2>&1 && alias ping='ping -b'
# Linux specific functions.
psgrep() {
ps -auwwx | egrep "(RSS|$1)"
}
elif [[ "$_PLATFORM" = "Darwin" ]]; then
# Darwin specific aliases.
hash df >/dev/null 2>&1 && alias df='df -P'
hash ls >/dev/null 2>&1 && alias ls='ls -bFG'
hash top >/dev/null 2>&1 && alias top='top -o cpu -S'
else
echo "${BASH_SOURCE##*/}: unsupported platform: $_PLATFORM" >&2
fi
unset _PLATFORM
# Common aliases.
hash bc >/dev/null 2>&1 && alias bc='bc -lq'
hash curl >/dev/null 2>&1 && alias pastebin="curl -F 'sprunge=<-' http://sprunge.us"
hash diff >/dev/null 2>&1 && alias diff='diff -u'
hash egrep >/dev/null 2>&1 && alias egrep='egrep --color=auto'
hash fgrep >/dev/null 2>&1 && alias fgrep='fgrep --color=auto'
hash grep >/dev/null 2>&1 && alias grep='grep --color=auto'
hash screen >/dev/null 2>&1 && alias screen='screen -Ua'