#!/usr/bin/env bash # Bash Finger client (RFC 1288) using /dev/tcp # Supports 8-bit chars, long files, ASCII art # License: Blue Oak Model License 1.0.0 # Install: chmod +x bfinger && sudo cp bfinger /usr/local/bin/ # uninstall: sudo rm /usr/local/bin/bfinger # v2.2 (2025-11-14): fixed help flags # v2.1 (2025-10-11): 128k Transfer limit as default, minor other edits # v2.0 (2025-05-30): Added Transfer limit (BFINGER_MAX_BYTES) & timeouts # v1.0 (2025-05-01): Initial release # ------------------------------ Start Script ------------------------------- set -eo pipefail [ -n "${DEBUG:-}" ] && set -xu VERSION="2.2 (Nov 14, 2025)" export LC_ALL=C cleanup() { exec 3<&- 3>&- 2>/dev/null || true exit 130 } trap cleanup INT # Transfer limit: default is ~128KB. Adjust as needed. MAX_BYTES=${BFINGER_MAX_BYTES:-128000} if [ $# -eq 0 ] || [[ "$1" =~ ^(-h|--help|/\?)$ ]]; then echo "" echo "bfinger $VERSION - A Bash-based Finger Client (RFC 1288)" echo "" echo "Uses Bash's /dev/tcp for socket connections to query remote Finger" echo "servers. Full support for 8-bit characters, long files and ASCII art." echo "" echo "Usage:" echo " bfinger @domain.com # Queries host" echo " bfinger user@domain.com # Specific user" echo " bfinger user domain.com # Alternative" echo " bfinger @localhost # fingerd must be installed locally" echo "" echo "Options:" echo " -v, --version Show version info" echo " -h, --help, /? Show this help message" echo "" echo "Examples:" echo " bfinger fingerverse@happynetbox.com | less" echo " bfinger @plan.cat | head -n 20" echo "" echo "install: chmod +x bfinger && sudo cp bfinger /usr/local/bin" echo "uninstall: sudo rm /usr/local/bin/bfinger" echo "" exit 0 fi if [[ "${1:-}" == "--version" || "${1:-}" == "-v" ]]; then echo echo "bfinger $VERSION - A Bash-based finger client" echo exit 0 fi if [[ "$1" == @* ]]; then USER="" HOST="${1#@}" elif [[ "$1" =~ @ ]]; then USER="${1%%@*}" HOST="${1##*@}" else USER="${1:-}" HOST="${2:-}" fi PORT=79 if [ -z "$HOST" ]; then echo "Error: No host specified" >&2 exit 1 fi if [[ ! "$HOST" =~ ^[a-zA-Z0-9._-]+$ ]]; then echo "Error: Hostname contains invalid characters" >&2 exit 1 fi if ! getent hosts "$HOST" >/dev/null; then echo "Error: Host '$HOST' could not be resolved" >&2 exit 1 fi if ! timeout 5 bash -c "exec 3<>/dev/tcp/$HOST/$PORT"; then echo "Error: Connection to $HOST:$PORT timed out or failed" >&2 echo "Tip: Try 'telnet $HOST $PORT' to debug" >&2 exit 1 fi exec 3<>/dev/tcp/"$HOST"/"$PORT" printf "%s\r\n" "$USER" >&3 bytes_read=0 while IFS= read -r -t 5 -N 1 char <&3 && (( bytes_read++ < MAX_BYTES )); do printf "%s" "$char" done (( bytes_read >= MAX_BYTES )) && echo >&2 (( bytes_read >= MAX_BYTES )) && echo "Output truncated after $MAX_BYTES bytes." >&2 exec 3<&- 3>&-