Add updated bash startup files.
This commit is contained in:
parent
1e3ead5c74
commit
ee8f5f528a
11 changed files with 633 additions and 593 deletions
220
.bashrc.d/git
Executable file
220
.bashrc.d/git
Executable file
|
@ -0,0 +1,220 @@
|
|||
#!/bin/bash - not strictly necessary, but helps nano with syntax highlighting.
|
||||
|
||||
__git_prompt_command() {
|
||||
# Perform git actions as part of PROMPT_COMMAND.
|
||||
# Environment variables:
|
||||
# GIT_PROMPT_COMMAND_DISABLE_PREFETCH=1 Disable automatic 'prefetch' of upstream refs.
|
||||
# This can also be disabled on a per repository basis using:
|
||||
# git config ---local -replace-all --type bool script.PromptCommandDisablePrefetch true
|
||||
# Returns: 0 = Tasks completed successfully.
|
||||
# 1 = An error occured.
|
||||
local GIT_REPO_INFO LC_ALL="C" NOW REPO_TIMESTAMP TIMESTAMP_VAR
|
||||
|
||||
# shellcheck disable=SC2207
|
||||
GIT_REPO_INFO=( $(git rev-parse --is-inside-work-tree --show-toplevel 2>/dev/null) ) || return 1
|
||||
|
||||
# Only process if in a work directory.
|
||||
[[ "${GIT_REPO_INFO[0]}" == "true" ]] && {
|
||||
# Run prefetch tasks if not disabled.
|
||||
[[ -z "$GIT_PROMPT_COMMAND_DISABLE_PREFETCH" ]] && [[ "$(git config --local --get --type bool script.PromptCommandDisablePrefetch 2>/dev/null)" != "true" ]] && {
|
||||
timeout --signal=KILL 7s git maintenance run --task=prefetch 2>/dev/null || {
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Git maintenance 'prefetch' task failed." >&2
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# The time now.
|
||||
if [[ "$PLATFORM" == "Linux" ]]; then
|
||||
NOW="$(date +'%s%3N')"
|
||||
elif [[ "$PLATFORM" == "Darwin" ]]; then
|
||||
NOW="$(perl -e 'use Time::HiRes; printf "%.3f", Time::HiRes::time();')"
|
||||
NOW="${NOW/.}"
|
||||
fi
|
||||
|
||||
# Determine the timestamp variable name depending on bash version.
|
||||
if (( BASH_VERSINFO[0] >= 4 )); then
|
||||
TIMESTAMP_VAR="GIT_REPO_TIMESTAMP[${GIT_REPO_INFO[1]//[^[:alnum:]]/_}]"
|
||||
else
|
||||
# This is going to pollute the environment, but Darwin is a PITA.
|
||||
TIMESTAMP_VAR="GIT_REPO_TIMESTAMP_${GIT_REPO_INFO[1]//[^[:alnum:]]/_}"
|
||||
fi
|
||||
|
||||
if [[ -n "${!TIMESTAMP_VAR}" ]]; then
|
||||
# Monitor the git repo.
|
||||
REPO_TIMESTAMP="$(git config --local --get --type int script.AutoMergeLast)"
|
||||
(( ${!TIMESTAMP_VAR:-0} < REPO_TIMESTAMP )) && {
|
||||
# Display message depending on status.
|
||||
if [[ "$(git config --local --get --type bool script.AutoMergeSuccess)" == "true" ]]; then
|
||||
printf "\\033[1;32m%s" "Git auto-merge succeeded for this repo."
|
||||
if [[ "${GIT_REPO_INFO[1]}" == "$HOME" ]]; then
|
||||
printf " %s\\033[0m\\n" "Re-source .bash* files."
|
||||
else
|
||||
printf "\\033[0m\\n"
|
||||
fi
|
||||
# Update the timestamp in the environment.
|
||||
declare -g "$TIMESTAMP_VAR"="$NOW"
|
||||
else
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Git auto-merge failed for this repo - correct manually." >&2
|
||||
fi
|
||||
}
|
||||
else
|
||||
# Just set the timestamp in the environment.
|
||||
declare -g "$TIMESTAMP_VAR"="$NOW"
|
||||
fi
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
__prompt_git_status() {
|
||||
# Generate a git branch/status prompt.
|
||||
# Based on git-prompt.sh by Shawn O. Pearce <spearce@spearce.org>.
|
||||
# Arguments:
|
||||
# $1 The printf format string for the prompt. Must include %s.
|
||||
# Environment variables:
|
||||
# GIT_PROMPT_DISABLE=1 Disable git prompt processing completely in this shell.
|
||||
# GIT_PROMPT_SHOW_TYPE=1 Show type of repository (Bare, Shallow).
|
||||
# GIT_PROMPT_SHOW_UPSTREAM=1 Show status of this repository compaired to upstream:
|
||||
# ?? - No upstream set.
|
||||
# == - Working tree is equal to upstream.
|
||||
# <> - Divergent from upstream.
|
||||
# >> or >x - Working tree is ahead of upstream (x = commits ahead when used with next option).
|
||||
# << or <x - Working tree is behind upstream (x = commits behind when used with next option).
|
||||
# GIT_PROMPT_SHOW_UPSTREAM_EXTENDED=1 In addition to upstream status, show the number of commits difference (inplies above).
|
||||
# GIT_PROMPT_SHOW_IGNORED=1 Show a ! if the current directory is ignored, or _ if the git operation was timed out.
|
||||
# GIT_PROMPT_SHOW_UNSTAGED=1 Show a * if there are unstaged changes (superceeded by above).
|
||||
# GIT_PROMPT_SHOW_UNCOMMITTED=1 Show a & if there are staged but uncommitted changes (superceeded by above).
|
||||
# GIT_PROMPT_SHOW_UNTRACKED=1 Show a + if there are untracked files in the working directory (superceeded by above).
|
||||
# GIT_PROMPT_SHOW_STASH=1 Show a $ if there is a stash in this repository (superceeded by above).
|
||||
# Displays: The printf formatted git prompt based upon $1 and the environment vaiables above, for example:
|
||||
# S:branch_name >5 *
|
||||
# Returns: 0 = Produced a prompt successfully, or returned because GIT_PROMPT_DISABLE=1 was set.
|
||||
# 1 = An error occured.
|
||||
local BRANCH COUNT GIT_PROMPT GIT_PROMPT_MARKER_SET GIT_REPO_INFO IFS=$'\n'
|
||||
|
||||
# Don't do anything if GIT_PROMPT_DISABLE is set.
|
||||
[[ -v GIT_PROMPT_DISABLE ]] && return 0
|
||||
|
||||
# Bail out if there's no format argument given, or it doesn't contain %s
|
||||
(( $# != 1 )) || [[ "$1" != *%s* ]] && return 1
|
||||
|
||||
# Get some repository information.
|
||||
# shellcheck disable=SC2207
|
||||
GIT_REPO_INFO=( $(git rev-parse --is-bare-repository --is-shallow-repository --is-inside-git-dir --is-inside-work-tree 2>/dev/null) ) || return 1
|
||||
|
||||
# Generate the prompt.
|
||||
if [[ "${GIT_REPO_INFO[2]}" == "true" ]]; then
|
||||
# In the git directory, use a special branch marker.
|
||||
GIT_PROMPT+="!GIT_DIR!"
|
||||
elif [[ "${GIT_REPO_INFO[3]}" == "true" ]]; then
|
||||
# In the working directory, generate the prompt.
|
||||
# Add type markers.
|
||||
[[ -n "$GIT_PROMPT_SHOW_TYPE" ]] && {
|
||||
if [[ "${GIT_REPO_INFO[0]}" == "true" ]]; then
|
||||
GIT_PROMPT+="B:"
|
||||
elif [[ "${GIT_REPO_INFO[1]}" == "true" ]]; then
|
||||
GIT_PROMPT+="S:"
|
||||
fi
|
||||
}
|
||||
|
||||
# Add the branch or a no commits marker.
|
||||
BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
|
||||
if [[ "$BRANCH" == "HEAD" ]]; then
|
||||
GIT_PROMPT+="?NO COMMITS?"
|
||||
|
||||
# Output the prompt and escape early.
|
||||
# shellcheck disable=SC2059
|
||||
printf -- "$1" "$GIT_PROMPT"
|
||||
return 0
|
||||
else
|
||||
GIT_PROMPT+="$BRANCH"
|
||||
fi
|
||||
|
||||
# Add upstream status.
|
||||
[[ -n "$GIT_PROMPT_SHOW_UPSTREAM" ]] || [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]] && {
|
||||
COUNT="$(git rev-list --count --left-right "${BRANCH:+refs/prefetch/remotes/origin/}${BRANCH:-@{upstream\}}...HEAD" 2>/dev/null | tr '[:blank:]' ' ')"
|
||||
case "$COUNT" in
|
||||
"")
|
||||
# No upstream.
|
||||
GIT_PROMPT+=" ??"
|
||||
;;
|
||||
"0 0")
|
||||
# Equal to upstream.
|
||||
GIT_PROMPT+=" =="
|
||||
;;
|
||||
"0 "*)
|
||||
# Ahead of upstream.
|
||||
GIT_PROMPT+=" >"
|
||||
if [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]]; then
|
||||
# Show the number of the difference.
|
||||
GIT_PROMPT+="${COUNT#0 }"
|
||||
else
|
||||
GIT_PROMPT+=">"
|
||||
fi
|
||||
;;
|
||||
*" 0")
|
||||
# Behind upstream.
|
||||
GIT_PROMPT+=" <"
|
||||
if [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]]; then
|
||||
# Show the number of the difference.
|
||||
GIT_PROMPT+="${COUNT% 0}"
|
||||
else
|
||||
GIT_PROMPT+="<"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Divergent from upstream.
|
||||
GIT_PROMPT+=" <>"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Add a marker if directory is ignored, there's unstaged files, uncommitted changes, untracked files or a stash.
|
||||
[[ -n "$GIT_PROMPT_SHOW_IGNORED" ]] && git check-ignore . >/dev/null 2>&1 && {
|
||||
GIT_PROMPT+=" !"
|
||||
GIT_PROMPT_MARKER_SET=1
|
||||
}
|
||||
[[ -z "$GIT_PROMPT_MARKER_SET" ]] && [[ -n "$GIT_PROMPT_SHOW_UNSTAGED" ]] && {
|
||||
timeout --signal=KILL 2s git ls-files --modified --exclude-standard --directory --error-unmatch -- ':/*' >/dev/null 2>&1
|
||||
ERR=$?
|
||||
if (( ERR == 124 )) || (( ERR == 137 )); then
|
||||
GIT_PROMPT+=" _"
|
||||
GIT_PROMPT_MARKER_SET=1
|
||||
elif (( ERR == 0 )); then
|
||||
GIT_PROMPT+=" *"
|
||||
GIT_PROMPT_MARKER_SET=1
|
||||
fi
|
||||
}
|
||||
[[ -z "$GIT_PROMPT_MARKER_SET" ]] && [[ -n "$GIT_PROMPT_SHOW_UNCOMMITTED" ]] && ! git diff --name-only --cached --exit-code >/dev/null 2>&1 && {
|
||||
GIT_PROMPT+=" &"
|
||||
GIT_PROMPT_MARKER_SET=1
|
||||
}
|
||||
[[ -z "$GIT_PROMPT_MARKER_SET" ]] && [[ -n "$GIT_PROMPT_SHOW_UNTRACKED" ]] && {
|
||||
timeout --signal=KILL 2s git ls-files git ls-files --others --exclude-standard --directory --error-unmatch -- ':/*' >/dev/null 2>&1
|
||||
ERR=$?
|
||||
if (( ERR == 124 )) || (( ERR == 137 )); then
|
||||
GIT_PROMPT+=" _"
|
||||
GIT_PROMPT_MARKER_SET=1
|
||||
elif (( ERR == 0 )); then
|
||||
GIT_PROMPT+=" +"
|
||||
GIT_PROMPT_MARKER_SET=1
|
||||
fi
|
||||
}
|
||||
[[ -z "$GIT_PROMPT_MARKER_SET" ]] && [[ -n "$GIT_PROMPT_SHOW_STASH" ]] && git rev-parse --verify --quiet refs/stash >/dev/null && {
|
||||
GIT_PROMPT+=" $"
|
||||
GIT_PROMPT_MARKER_SET=1
|
||||
}
|
||||
fi
|
||||
|
||||
# Output the prompt.
|
||||
# shellcheck disable=SC2059
|
||||
printf -- "$1" "$GIT_PROMPT"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Add the git prompt function call to PROMPT_COMMAND.
|
||||
PROMPT_COMMAND+="__git_prompt_command;"
|
||||
|
||||
# Add the git information to the prompt.
|
||||
PS1+='$(__prompt_git_status "\[\\033[1;35m\] (%s)\[\\033[0m\]")'
|
11
.bashrc.d/imagebin
Executable file
11
.bashrc.d/imagebin
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash - not strictly necessary, but helps nano with syntax highlighting.
|
||||
|
||||
imagebin() {
|
||||
# Throw an image file into imagebin.
|
||||
|
||||
[[ -z "$1" ]] || [[ ! -e "$1" ]] && {
|
||||
printf "%s: %s\\n" "Usage" "${FUNCNAME[0]} <filename>" >&2
|
||||
return 1
|
||||
}
|
||||
curl -F file="@$1" https://imagebin.ca/upload.php | grep '^url:' | cut -d: -f2-
|
||||
}
|
25
.bashrc.d/nanorc
Executable file
25
.bashrc.d/nanorc
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash - not strictly necessary, but helps nano with syntax highlighting.
|
||||
|
||||
__nanorc_prompt_command() {
|
||||
# Dynamically handle .nanorc file versions.
|
||||
|
||||
hash nano >/dev/null 2>&1 && {
|
||||
# Darwin specifc .nanorc version.
|
||||
[[ "$PLATFORM" == "Darwin" ]] && [[ "$(hash -t nano)" == "/usr/bin/nano" ]] && local NANO_VER="darwin"
|
||||
# shellcheck disable=SC2155
|
||||
[[ -v NANO_VER ]] || local NANO_VER="$(command nano --version | awk '/version/ { print $4 }' | cut -d. -f1)"
|
||||
|
||||
# Set the .nanorc symlink if it doesn't already point to the correct versioned file.
|
||||
if [[ -f "$HOME/.nanorc-$NANO_VER" ]]; then
|
||||
[[ "$(readlink "$HOME/.nanorc")" != ".nanorc-$NANO_VER" ]] && (cd "$HOME" && ln -sf ".nanorc-$NANO_VER" ".nanorc")
|
||||
else
|
||||
[[ -L "$HOME/.nanorc" ]] && rm -f "$HOME/.nanorc"
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "No .nanorc for version '$NANO_VER'." >&2
|
||||
fi
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Add the nanorc prompt function call to PROMPT_COMMAND.
|
||||
PROMPT_COMMAND+="__nanorc_prompt_command;"
|
243
.bashrc.d/ssh
Executable file
243
.bashrc.d/ssh
Executable file
|
@ -0,0 +1,243 @@
|
|||
#!/bin/bash - not strictly necessary, but helps nano with syntax highlighting.
|
||||
|
||||
__find_ssh_agent_sock() {
|
||||
# Find an *active* ssh agent socket.
|
||||
# Returns: 0 = Found an active socket.
|
||||
# 1 = Did not find a viable socket.
|
||||
local I
|
||||
|
||||
# Search the SSH_AUTH_SOCKS array for a viable socket.
|
||||
for ((I = 0; I < ${#SSH_AUTH_SOCKS[@]}; I++)); do
|
||||
[[ "${SSH_AUTH_SOCKS[$I]}" =~ ^[[:blank:]]*$ ]] && continue
|
||||
SSH_AUTH_SOCK="${SSH_AUTH_SOCKS[$I]}" ssh-add -l >/dev/null 2>&1
|
||||
(( $? <= 1 )) && {
|
||||
export SSH_AUTH_SOCK="${SSH_AUTH_SOCKS[$I]}"
|
||||
return 0
|
||||
}
|
||||
unset SSH_AUTH_SOCK
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
__read_ssh_agents() {
|
||||
# Read all the known ssh agent sockets into an array.
|
||||
# Returns: 0 = Processed and read the agents file without issue.
|
||||
# 1 = Error processing/reading the agents file.
|
||||
local ERR I SOCK
|
||||
|
||||
[[ ! -e "$HOME/.ssh/agents" ]] && touch "$HOME/.ssh/agents"
|
||||
|
||||
# Lock the ~/.ssh/agents file.
|
||||
if [[ "$PLATFORM" == "Linux" ]]; then
|
||||
# Linux has 'flock', thankfully.
|
||||
exec 9<"$HOME/.ssh/agents" && flock -E 10 -e -w 0.5 9
|
||||
ERR=$?
|
||||
if (( ERR == 10 )); then
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Failed to obtain lock on ~/.ssh/agents." >&2
|
||||
return 1
|
||||
elif (( ERR > 0 )); then
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Flock usage error." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Make note of the mtime for use in write_ssh_agents.
|
||||
SSH_AGENTS_MTIME="$(stat --format=%.9Y "$HOME/.ssh/agents")"
|
||||
elif [[ "$PLATFORM" == "Darwin" ]]; then
|
||||
# Do locking the sucky way on Darwin.
|
||||
for ((I = 0; I <= 5; I++)); do
|
||||
if shlock -p "$$" -f "$HOME/.ssh/agents.lock"; then
|
||||
exec 9<"$HOME/.ssh/agents"
|
||||
# Make note of the mtime for use in write_ssh_agents.
|
||||
SSH_AGENTS_MTIME="$(stat -f %Fm "$HOME/.ssh/agents")"
|
||||
ERR=0
|
||||
break
|
||||
else
|
||||
ERR=1
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
(( ERR != 0 )) && {
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Failed to obtain lock on ~/.ssh/agents." >&2
|
||||
return 1
|
||||
}
|
||||
else
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "File locking unsupported on '$PLATFORM'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Read the socket list (bash v2+ compliant)
|
||||
while read -u 9 -r SOCK; do
|
||||
[[ -n "$SOCK" ]] && SSH_AUTH_SOCKS+=("$SOCK")
|
||||
done
|
||||
ERR=$?
|
||||
|
||||
# Close the file descriptor (which on Linux releases the flock too).
|
||||
exec 9<&-
|
||||
|
||||
# On Darwin, release the lock on the file.
|
||||
rm -f "$HOME/.ssh/agents.lock"
|
||||
|
||||
# Remove the . in the mtime.
|
||||
SSH_AGENTS_MTIME="${SSH_AGENTS_MTIME/\.}"
|
||||
|
||||
# Error out if the data couldn't be read.
|
||||
(( ERR != 0 )) && {
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Failed to read ssh-agent socket list." >&2
|
||||
unset SSH_AUTH_SOCKS SSH_AGENTS_MTIME
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
__ssh_agent_prompt_command() {
|
||||
# If necessary, find and activate a new ssh agent socket before each prompt is displayed.
|
||||
# Returns: 0 = All is good.
|
||||
# 1 = An error occured.
|
||||
local ERR
|
||||
|
||||
if [[ -z "$SSH_AUTH_SOCK" ]]; then
|
||||
ERR=2
|
||||
else
|
||||
ssh-add -l >/dev/null 2>&1
|
||||
ERR=$?
|
||||
fi
|
||||
(( ERR == 2 )) && {
|
||||
# Read alternative sockets from ~/.ssh/agents.
|
||||
__read_ssh_agents || {
|
||||
unset SSH_AUTH_SOCK
|
||||
return 1
|
||||
}
|
||||
|
||||
# Find a new socket to use.
|
||||
if __find_ssh_agent_sock; then
|
||||
printf "\\033[1;33m%s\\033[0m\\n" "Connected to existing ssh-agent socket."
|
||||
sleep 0.5
|
||||
else
|
||||
# Start a new agent.
|
||||
eval "$(ssh-agent -s 2>/dev/null | grep -v 'echo'; printf "%s" "ERR=${PIPESTATUS[0]}")"
|
||||
(( ERR > 0 )) && {
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Failed to start new ssh-agent - continuing with no agent."
|
||||
sleep 0.5
|
||||
return 1
|
||||
}
|
||||
printf "\\033[1;32m%s\\033[0m\\n" "Started new ssh-agent."
|
||||
__write_ssh_agents
|
||||
(( $? == 2 )) && __read_ssh_agents && __write_ssh_agents
|
||||
sleep 0.5
|
||||
fi
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
__write_ssh_agents() {
|
||||
# Write all unique ssh agent sockets into the ~/.ssh/agents file.
|
||||
# Returns: 0 = Processed and wrote the agents file without issue.
|
||||
# 1 = Error processing/writing the agents file.
|
||||
# 2 = The SSH_AUTH_SOCKS array may be out of date as the agents file'a mtime has changed.
|
||||
local ERR I J MTIME SOCKS
|
||||
|
||||
# Add the current agent socket to the sockets array.
|
||||
SSH_AUTH_SOCKS=("$SSH_AUTH_SOCK" "${SSH_AUTH_SOCKS[@]}")
|
||||
|
||||
# Remove any duplicates from SSH_AUTH_SOCKS.
|
||||
for ((I = 0; I < ${#SSH_AUTH_SOCKS[@]}; I++)); do
|
||||
[[ -z "${SSH_AUTH_SOCKS[$I]}" ]] && continue
|
||||
for ((J = 0; J < ${#SOCKS[@]}; J++)); do
|
||||
[[ "${SSH_AUTH_SOCKS[$I]}" == "${SOCKS[$J]}" ]] && continue 2
|
||||
done
|
||||
# Only add the socket if it's still viable.
|
||||
SSH_AUTH_SOCK="${SSH_AUTH_SOCKS[$I]}" ssh-add -l >/dev/null 2>&1
|
||||
(( $? <= 1 )) && SOCKS+=("${SSH_AUTH_SOCKS[$I]}")
|
||||
done
|
||||
|
||||
# Lock the ~/.ssh/agents file.
|
||||
if [[ "$PLATFORM" == "Linux" ]]; then
|
||||
# Make sure SSH_AUTH_SOCKS has the most up to date data.
|
||||
MTIME="$(stat --format=%.9Y "$HOME/.ssh/agents")"
|
||||
(( ${MTIME/\.} > SSH_AGENTS_MTIME )) && return 2
|
||||
|
||||
# Lock the agents file.
|
||||
exec 9<"$HOME/.ssh/agents" && flock -E 10 -e -w 0.5 9
|
||||
ERR=$?
|
||||
if (( ERR == 10 )); then
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Failed to obtain lock on ~/.ssh/agents." >&2
|
||||
return 1
|
||||
elif (( ERR > 0 )); then
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Flock usage error." >&2
|
||||
return 1
|
||||
fi
|
||||
elif [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
# Make sure SSH_AUTH_SOCKS has the most up to date data.
|
||||
MTIME="$(stat -f %Fm "$HOME/.ssh/agents")"
|
||||
(( ${MTIME/\.} > SSH_AGENTS_MTIME )) && return 2
|
||||
|
||||
# Do locking the sucky way on Darwin.
|
||||
for ((I = 0; I <= 5; I++)); do
|
||||
if shlock -p "$$" -f "$HOME/.ssh/agents.lock"; then
|
||||
exec 9<"$HOME/.ssh/agents"
|
||||
ERR=0
|
||||
break
|
||||
else
|
||||
ERR=1
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
(( ERR != 0 )) && {
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Failed to obtain lock on ~/.ssh/agents." >&2
|
||||
return 1
|
||||
}
|
||||
else
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "File locking unsupported on '$PLATFORM'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Write the cleaned array to disk.
|
||||
ERR=-1
|
||||
[[ -n "${SOCKS[*]}" ]] && { printf "%s\\n" "${SOCKS[@]}" >"$HOME/.ssh/agents" 2>/dev/null; ERR=$?; }
|
||||
|
||||
# Release locks.
|
||||
exec 9<&-
|
||||
rm -f "$HOME/.ssh/agents.lock"
|
||||
|
||||
# Error out if the data couldn't be written.
|
||||
if (( ERR == -1 )); then
|
||||
rm -f "$HOME/.ssh/agents" 2>/dev/null
|
||||
elif (( ERR >= 1 )); then
|
||||
rm -f "$HOME/.ssh/agents" 2>/dev/null
|
||||
printf "\\033[1;31m%s\\033[0m\\n" "Failed to write ssh-agent socket list." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Add the ssh-agent prompt function call to PROMPT_COMMAND.
|
||||
PROMPT_COMMAND+="__ssh_agent_prompt_command;"
|
||||
|
||||
# Auto start the ssh agent.
|
||||
__ssh_agent_prompt_command
|
||||
|
||||
# Prompt to add keys to ssh-agent with scp/sftp/ssh commands.
|
||||
hash scp ssh ssh-add >/dev/null 2>&1 && alias scp='_SSHEXEC=scp ssh'
|
||||
hash sftp ssh ssh-add >/dev/null 2>&1 && alias sftp='_SSHEXEC=sftp ssh'
|
||||
hash ssh ssh-add >/dev/null 2>&1 && ssh() {
|
||||
local ERR
|
||||
|
||||
if [[ -z "$SSH_AUTH_SOCK" ]]; then
|
||||
ERR=2
|
||||
else
|
||||
ssh-add -l >/dev/null 2>&1
|
||||
ERR=$?
|
||||
fi
|
||||
if (( ERR == 1 )); then
|
||||
ssh-add
|
||||
elif (( ERR == 2 )); then
|
||||
__ssh_agent_prompt_command
|
||||
ssh-add
|
||||
fi
|
||||
command "${_SSHEXEC:-ssh}" "$@"
|
||||
unset _SSHEXEC
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue