package main // 24 Aug 2026: Added support for the "finger://host[/user]" URL format // Maintained original author's commenting style // Original by: https://github.com/Lindax28/finger-client // Updates by: https://640kb.neocities.org/fingerverse // go build -o lindax2 import ( "fmt" "net" "os" "strings" "unicode" ) func main() { // Verify number of arguments is correct if len(os.Args) != 2 { fmt.Println("Usage: finger [user@hostname | finger://hostname(/user)]") os.Exit(1) } // Parse the argument - support both formats user, hostname, err := parseFingerArgument(os.Args[1]) if err != nil { fmt.Println(err) os.Exit(1) } // Verify username is in ASCII format (if provided) if user != "" { for _, char := range user { if char > unicode.MaxASCII { fmt.Println("Username must be in ASCII format") os.Exit(1) } } } // Connect to host on port 79 conn, err := net.Dial("tcp", hostname+":79") if err != nil { fmt.Println(err) os.Exit(1) } defer conn.Close() // Write user data to the connection, ended with CRLF // If user is empty, just send CRLF to query all users conn.Write([]byte(user + "\r\n")) // Read data from the connection response := make([]byte, 0) tmp := make([]byte, 256) for { n, err := conn.Read(tmp) if err != nil { break } response = append(response, tmp[:n]...) } fmt.Println(string(response)) } // parseFingerArgument parses either "user@host" or "finger://host[/user]" format func parseFingerArgument(arg string) (user, hostname string, err error) { // Check for finger:// format if strings.HasPrefix(arg, "finger://") { // Remove the "finger://" prefix withoutPrefix := strings.TrimPrefix(arg, "finger://") // Split by "/" - could be host/user or just host parts := strings.SplitN(withoutPrefix, "/", 2) if len(parts) == 1 { // Just hostname - query all users hostname = parts[0] if hostname == "" { return "", "", fmt.Errorf("Invalid finger:// format. Use: finger://hostname[/user]") } return "", hostname, nil } // host/user format hostname = parts[0] user = parts[1] if hostname == "" { return "", "", fmt.Errorf("Invalid finger:// format. Use: finger://hostname[/user]") } return user, hostname, nil } // Try user@host format parts := strings.SplitN(arg, "@", 2) if len(parts) != 2 { return "", "", fmt.Errorf("Proper Usage is: finger user@hostname") } user = parts[0] hostname = parts[1] // Validate we got something if user == "" || hostname == "" { return "", "", fmt.Errorf("Proper Usage is: finger user@hostname") } return user, hostname, nil }