ITHCWY: Robert Ellison's Blog

Personal Finger Daemon for Windows

Did you know that Windows still has a vestigial finger command with just about nothing left to talk to? One of my New Year's resolutions is to bring finger back and unlike the stalled webfinger project I need to make some progress. Here's some C# to run your own personal finger daemon... you just need to create a .plan file in your home directory (haven't done that for a while):

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace fingerd
    static class Program
        private const int FingerPort = 79;
        private const int MaxFingerCommand = 256;
        private const string PlanFile = ".plan";

        private static readonly TcpListener _tcpListener = new TcpListener(
             IPAddress.Any, FingerPort);

        static void Main()

            while (true)
                TcpClient tcpClient = _tcpListener.AcceptTcpClient();
                Thread clientThread = new Thread(ClientThread);

        static void ClientThread(object client)
            NetworkStream clientStream = null;
            TcpClient tcpClient = client as TcpClient;
            if (tcpClient == null) { return; }

                byte[] command = new byte[MaxFingerCommand];
                clientStream = tcpClient.GetStream();

                int read = clientStream.Read(command, 0, command.Length);
                if (read == 0) { return; }

                ASCIIEncoding asciiEncoding = new ASCIIEncoding();
                string commandText = asciiEncoding.GetString(command);

                int endOfCommand = commandText.IndexOf("\r\n"
                if (endOfCommand <= 0) { return; }

                string user = commandText.Substring(0, endOfCommand);
                if (string.Compare(user, Environment.UserName, 
                    StringComparison.InvariantCultureIgnoreCase) != 0) { return; }

                string planPath = Path.Combine(Environment.GetFolderPath(
                if (!File.Exists(planPath)) { return; }

                string plan = File.ReadAllText(planPath) + "\r\n";
                byte[] planBytes = asciiEncoding.GetBytes(plan);
                clientStream.Write(planBytes, 0, planBytes.Length);
            catch (Exception ex)
                if (clientStream != null)

Add Comment

All comments are moderated to weed out spam. Email address is optional and is only used to display your Gravatar.