I Thought He Came With You is Robert Ellison’s blog about software, marketing, politics, photography and time lapse.

Personal Finger Daemon for Windows

Updated on Thursday, November 12, 2015

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. Your email address is used to display a Gravatar and optionally for notification of new comments and to sign up for the newsletter.