ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSFinger/CCSFinger.cs
Revision: 722
Committed: 2006-03-30T20:45:16-08:00 (19 years, 3 months ago) by douglas
File size: 8403 byte(s)
Log Message:
This may be as far as it gets to figuring out the "Connection reset by peer" problem, onward!

File Contents

# User Rev Content
1 douglas 719 // Douglas Thrift
2 douglas 710 //
3     // CCS Computer Science
4     //
5     // Windows Finger Daemon
6    
7     using System;
8     using System.Collections.Generic;
9     using System.IO;
10     using System.Net;
11     using System.Net.Sockets;
12     using System.ServiceProcess;
13     using System.Text;
14     using System.Threading;
15    
16     public class CCSFinger : ServiceBase
17     {
18     private class Finger
19     {
20     private class Login
21     {
22 douglas 718 private Net.USER_INFO_11 info;
23 douglas 710 private uint id;
24     private string session;
25 douglas 718 private string client;
26     private Wts.WTS_PROTOCOL_TYPE protocol;
27     private Wts.WTS_CONNECTSTATE_CLASS status;
28     private DateTime logon = DateTime.MinValue;
29 douglas 710
30 douglas 718 public Login(string login)
31 douglas 710 {
32 douglas 718 Net.UserGetInfo(null, login, 11, out info);
33 douglas 710
34 douglas 718 this.id = uint.MaxValue;
35     }
36    
37     public Login(string login, uint id, string session, string client, Wts.WTS_PROTOCOL_TYPE protocol, Wts.WTS_CONNECTSTATE_CLASS status)
38     {
39     Net.UserGetInfo(null, login, 11, out info);
40    
41 douglas 710 this.id = id;
42     this.session = session;
43 douglas 718 this.client = client;
44     this.protocol = protocol;
45     this.status = status;
46 douglas 710 }
47    
48 douglas 718 public string Client
49 douglas 710 {
50 douglas 718 get { return protocol == Wts.WTS_PROTOCOL_TYPE.WTS_PROTOCOL_TYPE_CONSOLE ? "the Console" : client; }
51 douglas 710 }
52    
53     public string Directory
54     {
55     get { return @"\\Zweihander\" + info.usri11_name; }
56     }
57    
58     public uint Id
59     {
60     get { return id; }
61     }
62    
63 douglas 718 public DateTime LastLogon
64     {
65     get
66     {
67     if (logon == DateTime.MinValue)
68     logon = new DateTime(1970, 1, 1) + new TimeSpan((long)info.usri11_last_logon * 10000000);
69    
70     return logon;
71     }
72     }
73    
74 douglas 710 public string Name
75     {
76     get { return info.usri11_full_name; }
77     }
78    
79     public string Session
80     {
81     get { return session; }
82     }
83 douglas 718
84     public string Status
85     {
86     get { return status.ToString().Substring(3); }
87     }
88 douglas 710 }
89    
90 douglas 722 private StreamWriter writer;
91 douglas 710 private SortedDictionary<string, List<Login>> logins = new SortedDictionary<string, List<Login>>();
92 douglas 721 private bool forward = false;
93 douglas 718 private List<string> nots = new List<string>();
94 douglas 710
95     private void Full()
96     {
97 douglas 721 if (forward)
98     writer.Write("finger: forwarding service denied\r\n");
99    
100 douglas 718 foreach (string not in nots)
101     writer.Write("finger: {0}: no such user\r\n", not);
102    
103 douglas 710 bool first = true;
104    
105     foreach (KeyValuePair<string, List<Login>> login in logins)
106     {
107     if (first)
108 douglas 720 first = false;
109 douglas 710 else
110     writer.Write("\r\n");
111    
112     writer.Write("Login: {0,-32} Name: {1}\r\nDirectory: {2}\r\n", login.Key, login.Value[0].Name, login.Value[0].Directory);
113    
114     foreach (Login login_ in login.Value)
115 douglas 718 if (login_.Id != uint.MaxValue)
116     writer.Write("{0} on {1}, from {2}\r\n", login_.Status, login_.Id, login_.Client);
117 douglas 710
118 douglas 720 if (login.Value[0].LastLogon != new DateTime(1970, 1, 1))
119     writer.Write("Last login {0:ddd MMM dd HH:mm} ({1})\r\n", login.Value[0].LastLogon.ToLocalTime(), login.Value[0].LastLogon.ToLocalTime().IsDaylightSavingTime() ? "PDT" : "PST");
120     else
121     writer.Write("Never logged in.\r\n");
122 douglas 718
123 douglas 720 writer.Write("No Mail.\r\n");
124    
125 douglas 710 string[] files = { ".project", ".plan" };
126    
127     foreach (string file in files)
128     try
129     {
130     StreamReader reader = new StreamReader(new FileStream(Directory.GetFiles(login.Value[0].Directory, file)[0], FileMode.Open, FileAccess.Read));
131    
132     switch (file)
133     {
134     case ".project":
135     writer.Write("Project:\r\n");
136     break;
137     case ".plan":
138     writer.Write("Plan:\r\n");
139     break;
140     }
141    
142 douglas 720 writer.Write("{0}", reader.ReadToEnd());
143 douglas 710 }
144 douglas 720 catch (Exception)
145     {
146     if (file == ".plan")
147     writer.Write("No Plan.\r\n");
148     }
149 douglas 710 }
150     }
151    
152 douglas 718 private void Sessions(IDictionary<string, List<Login>> logins)
153 douglas 710 {
154 douglas 718 Wts.WTS_SESSION_INFO[] sessions;
155     uint count;
156 douglas 710
157 douglas 718 Wts.EnumerateSessions(IntPtr.Zero, 0, 1, out sessions, out count);
158 douglas 710
159     for (uint index = 0; index != count; ++index)
160     {
161 douglas 718 string name;
162     uint size;
163 douglas 710
164 douglas 718 Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSUserName, out name, out size);
165 douglas 710
166     if (name.Length > 0)
167     {
168 douglas 718 string session, client;
169     Wts.WTS_PROTOCOL_TYPE protocol;
170     Wts.WTS_CONNECTSTATE_CLASS status;
171 douglas 710
172 douglas 718 Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSWinStationName, out session, out size);
173     Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSClientName, out client, out size);
174     Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSClientProtocolType, out protocol, out size);
175     Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSConnectState, out status, out size);
176 douglas 710
177     if (!logins.ContainsKey(name))
178     logins.Add(string.Copy(name), new List<Login>());
179    
180 douglas 718 logins[name].Add(new Login(name, sessions[index].SessionId, session, client, protocol, status));
181 douglas 710 }
182     }
183 douglas 718 }
184 douglas 710
185 douglas 722 public Finger(StreamWriter writer, bool full)
186 douglas 718 {
187 douglas 722 this.writer = writer;
188    
189 douglas 718 Sessions(logins);
190 douglas 710
191     if (logins.Count < 1)
192     writer.Write("No one logged on.\r\n");
193     else if (full)
194     Full();
195     else
196     {
197     writer.Write("Login Name Id Session Status\r\n");
198    
199     foreach (KeyValuePair<string, List<Login>> login_ in logins)
200     foreach (Login login in login_.Value)
201 douglas 718 writer.Write("{0,-15} {1,-20} {2,-6} {3,-13} {4}\r\n", login_.Key, login.Name.Length > 20 ? login.Name.Substring(0, 20) : login.Name, login.Id, login.Session, login.Status);
202 douglas 710 }
203     }
204    
205 douglas 722 public Finger(StreamWriter writer, ICollection<string> names)
206 douglas 710 {
207 douglas 722 this.writer = writer;
208    
209 douglas 718 uint count;
210     Net.NET_DISPLAY_USER[] users;
211 douglas 710
212 douglas 718 Net.QueryDisplayInformation(null, 1, 0, 100, uint.MaxValue, out count, out users);
213 douglas 710
214 douglas 718 Dictionary<string, List<Login>> logins_ = new Dictionary<string, List<Login>>();
215    
216     Sessions(logins_);
217    
218 douglas 710 foreach (string name in names)
219 douglas 721 if (name.Contains("@"))
220     forward = true;
221     else
222     {
223     bool not = true;
224 douglas 718
225 douglas 721 for (uint index = 0; index != count; ++index)
226     if (users[index].usri1_name.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1 || users[index].usri1_full_name.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1 && !logins.ContainsKey(users[index].usri1_name))
227     {
228     logins.Add(users[index].usri1_name, new List<Login>());
229 douglas 710
230 douglas 721 logins[users[index].usri1_name].Add(new Login(users[index].usri1_name));
231 douglas 718
232 douglas 721 if (logins_.ContainsKey(users[index].usri1_name))
233     logins[users[index].usri1_name].AddRange(logins_[users[index].usri1_name]);
234 douglas 718
235 douglas 721 not = false;
236     }
237 douglas 710
238 douglas 721 if (not)
239     nots.Add(name);
240     }
241 douglas 710
242     Full();
243     }
244     }
245    
246 douglas 720 private static void Do()
247 douglas 710 {
248     TcpListener listener = null;
249    
250     try
251     {
252     listener = new TcpListener(IPAddress.Any, 79);
253    
254     listener.Start();
255    
256     while (true)
257     {
258 douglas 722 Socket socket = listener.AcceptSocket();
259 douglas 721
260 douglas 722 socket.ReceiveTimeout = 60000;
261 douglas 721
262 douglas 710 Thread thread = new Thread(new ParameterizedThreadStart(Do));
263    
264 douglas 722 thread.Start(socket);
265 douglas 710 }
266     }
267     catch (SocketException exception)
268     {
269     Console.Error.WriteLine(exception);
270     }
271     finally
272     {
273     listener.Stop();
274     }
275 douglas 720 }
276 douglas 710
277 douglas 722 private static void Do(object socket_)
278 douglas 710 {
279 douglas 722 Socket socket = (Socket)socket_;
280     NetworkStream stream = new NetworkStream(socket);
281 douglas 710
282 douglas 722 try
283     {
284     byte[] buffer = new byte[1024];
285     int size = 0, byte_;
286 douglas 710
287 douglas 722 while (size != buffer.Length && (byte_ = stream.ReadByte()) != '\r' && byte_ != '\n' && byte_ != -1)
288     buffer[size++] = (byte)byte_;
289 douglas 710
290 douglas 722 string line = Encoding.ASCII.GetString(buffer, 0, size);
291    
292     Console.WriteLine("{0} [{1}]", socket.RemoteEndPoint, line);
293    
294     List<string> names = new List<string>();
295     bool full = false;
296    
297     foreach (string name in line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
298     {
299     if (name.ToUpper() == "/W")
300     full = true;
301     else
302     names.Add(name);
303     }
304    
305     StreamWriter writer = new StreamWriter(stream, new UTF8Encoding(false));
306    
307     Finger finger = names.Count > 0 ? new Finger(writer, names) : new Finger(writer, full);
308    
309     writer.Flush();
310 douglas 710 }
311 douglas 722 catch (IOException) {}
312 douglas 710
313 douglas 722 socket.Close(60);
314 douglas 710 }
315    
316     public static int Main(string[] args)
317     {
318 douglas 721 Do();
319 douglas 710
320     return 0;
321     }
322     }