finger.bash
edited
1#!/usr/bin/env bash
2# SPDX-License-Identifier: MIT
3
4# finger.bash
5# A simple finger client written in pure Bash
6
7# Copyright © 2025 Giuseppe Masino <self@qub1750ul.me>
8#
9# Permission is hereby granted, free of charge, to any person obtaining a
10# copy of this software and associated documentation files (the “Software”),
11# to deal in the Software without restriction, including without limitation
12# the rights to use, copy, modify, merge, publish, distribute, sublicense,
13# and/or sell copies of the Software, and to permit persons to whom the
14# Software is furnished to do so, subject to the following conditions:
15#
16# The above copyright notice and this permission notice shall be included in
17# all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25# DEALINGS IN THE SOFTWARE.
26
27set -o errexit
28set -o nounset
29set -o pipefail
30shopt -s lastpipe
31
32log() { builtin echo "finger.bash: $*" >&2 ;}
33info() { log "INFO: $*" ;}
34warn() { log "WARN: $*" ;}
35error() { log "ERROR: $*" ; }
36
37finger()
38{
39 if ! [[ "$*" =~ (^[^@ ]+)?(@([^\/: ]+)(:([0-9]+))?)? ]] ; then
40 error "'$1'" is not a valid finger URI
41 exit 1
42 fi
43
44 declare -g subject="${BASH_REMATCH[1]:-}"
45 declare -g host="${BASH_REMATCH[3]:-${host:-localhost}}"
46 declare -g port="${BASH_REMATCH[5]:-${port:-79}}"
47 npCharWarned=false
48
49 info "querying $host:$port"
50 exec 3<>"/dev/tcp/${host}/${port}"
51
52 if ! [ -e /proc/$$/fd/3 ] ; then
53 error "failed establishing connection"
54 exit 1
55 fi
56
57 printf "%s\r\n" "$subject" >&3
58 while read -r ; do
59
60 if [[ "$REPLY" =~ "[^ -~]+" ]] && ! $npCharWarned ; then
61 warn "server returned non printable data. Stripping it."
62 npCharWarned=true
63 fi
64
65 echo "${REPLY//[^ -~]/}"
66 done <&3
67 npCharWarned=false
68}
69
70if ! [ "$1" = "-i" ] ; then
71 finger "$@" && exit 0
72else
73 shift
74 finger "$@"
75 while read -p 'finger> ' -r query ; do case "$query" in
76 ('') ;;
77 (\?) finger ;;
78 ('\?') finger ? ;;
79 (*) finger "$query" ;;
80 esac ; done
81fi