From d06397195c00906eac7ed9cd2c8712f3da53f91d Mon Sep 17 00:00:00 2001 From: mysticbbs Date: Sun, 23 Sep 2012 00:59:43 -0400 Subject: [PATCH] NodeSpy telnet client --- mystic/HISTORY.txt | 4 + mystic/nodespy.pas | 118 ++------------- mystic/nodespy_ansiterm.ans | 4 +- mystic/nodespy_ansiterm.pas | 23 ++- mystic/nodespy_common.pas | 3 +- mystic/nodespy_term.pas | 277 ++++++++++++++++++++++++++++++++---- 6 files changed, 281 insertions(+), 148 deletions(-) diff --git a/mystic/HISTORY.txt b/mystic/HISTORY.txt index 35228c1..7b7c9cc 100644 --- a/mystic/HISTORY.txt +++ b/mystic/HISTORY.txt @@ -4838,3 +4838,7 @@ + NodeSpy in Windows now uses OS named pipes instead of Disk I/O. + NodeSpy in Unix now uses OS named pipes instead of Disk I/O. + + + NodeSpy now has a full blown telnet client, which replaces the "local + login" feature. Instead, my default the phone book will contain an entry + for "local login" which just telnets to localhost. diff --git a/mystic/nodespy.pas b/mystic/nodespy.pas index 15b659c..2579a8d 100644 --- a/mystic/nodespy.pas +++ b/mystic/nodespy.pas @@ -29,6 +29,10 @@ Program NodeSpy; {$I M_OPS.PAS} Uses + {$IFDEF DEBUG} + HeapTrc, + LineInfo, + {$ENDIF} {$IFDEF UNIX} BaseUnix, {$ENDIF} @@ -39,10 +43,10 @@ Uses m_Pipe, m_Input, m_Output, - m_io_Base, - m_io_Sockets, m_Term_Ansi, - NodeSpy_Common; + m_IniReader, + NodeSpy_Common, + NodeSpy_Term; Const HiddenNode = 255; @@ -109,6 +113,7 @@ Var Info : Stat; {$ENDIF} Count : Byte; + INI : TIniReader; Begin {$IFDEF UNIX} If fpStat('nodespy', Info) = 0 Then Begin @@ -460,107 +465,6 @@ Begin AutoSnoopID := NodeInfo[Node]^.ID; End; -Procedure LocalLogin; -Const - BufferSize = 1024 * 4; -Var - Client : TIOSocket; - Res : LongInt; - Buffer : Array[1..BufferSize] of Char; - Done : Boolean; - Ch : Char; -Begin - Screen.SetWindowTitle('NodeSpy/Terminal'); - - Screen.TextAttr := 7; - Screen.ClearScreen; - - Screen.WriteStr ('Connecting to 127.0.0.1... '); - - Client := TIOSocket.Create; - - Client.FTelnetClient := True; - - If Not Client.Connect('127.0.0.1', Config.INetTNPort) Then - ShowMsgBox (0, 'Unable to connect') - Else Begin - Done := False; - Term := TTermAnsi.Create(Screen); - - If Config.UseStatusBar Then Begin - Screen.SetWindow (1, 1, 80, 24, True); - Screen.WriteXY (1, 25, Config.StatusColor3, strPadC('Local TELNET: ALT-X to Quit', 80, ' ')); - End; - - Term.SetReplyClient(TIOBase(Client)); - - Repeat - If Client.WaitForData(0) > 0 Then Begin - Repeat - Res := Client.ReadBuf (Buffer, BufferSize); - - If Res < 0 Then Begin - Done := True; - Break; - End; - - Term.ProcessBuf(Buffer, Res); - Until Res <> BufferSize; - End Else - If Keyboard.KeyPressed Then Begin - Ch := Keyboard.ReadKey; - Case Ch of - #00 : Case Keyboard.ReadKey of - #45 : Break; - #71 : Client.WriteStr(#27 + '[H'); - #72 : Client.WriteStr(#27 + '[A'); - #73 : Client.WriteStr(#27 + '[V'); - #75 : Client.WriteStr(#27 + '[D'); - #77 : Client.WriteStr(#27 + '[C'); - #79 : Client.WriteStr(#27 + '[K'); - #80 : Client.WriteStr(#27 + '[B'); - #81 : Client.WriteStr(#27 + '[U'); - #83 : Client.WriteStr(#127); - End; - Else - Client.WriteBuf(Ch, 1); - If Client.FTelnetEcho Then Term.Process(Ch); - End; - End Else - WaitMS(5); - Until Done; - - Term.Free; - End; - - Client.Free; - - Screen.TextAttr := 7; - Screen.SetWindow (1, 1, 80, 25, True); -End; - -Procedure Terminal; -Type - PhoneRec = Record - Name : String[40]; - Address : String[60]; - User : String[30]; - Password : String[20]; - StatusBar : Boolean; - End; - -Var - Book : Array[1..200] of PhoneRec; - -Begin - // create phonebook - // write phonebook - // load phonebook - // do directory - - // name, address, user, password, statusbar, sysop, software -End; - Procedure UpdateOnlineStatus; Var Count : LongInt; @@ -809,7 +713,7 @@ Begin FullReDraw; End; #32 : Begin - LocalLogin; + Terminal; FullReDraw; End; #27 : Break; @@ -845,6 +749,10 @@ Begin End; Begin + {$IFDEF DEBUG} + SetHeapTraceOutput('nodespy.mem'); + {$ENDIF} + ApplicationInit; MainMenu; diff --git a/mystic/nodespy_ansiterm.ans b/mystic/nodespy_ansiterm.ans index f67a0f4..ba0cb99 100644 --- a/mystic/nodespy_ansiterm.ans +++ b/mystic/nodespy_ansiterm.ans @@ -7,5 +7,5 @@ °°²ÛÛÛÛ ²ÜÜÜܲ ÛÛÛÛÛ ±Ü ßßßßÛÛÛÛ²ÛÛÛÛÛÛÛÛÛÛ²± ßÛÛÛÛÜÜÛÛÛÛÛ±°°°°°ßÛÛÛÛÜÜÜÜÜ ÜÜÛ ÜÜþ ßß² ± °°²ÜÜÜÜÜÜܲßßßßß ²ÛÛÛ ²²²ÛÛÛ²ßßßß ÞÜÜ ßßßßßßßß ßßßßß ßßßßßßß Ý°° °Ý°°þ Þßßßßßßßßßßßßß ß Node Spy ßÜ -ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜܲ System Name ²³² Address ²³² LastCall ²³² Calls ²Ûßßßßßßßßßßßßßßßßßßßßßßßßßßß³ßßßßßßßßßßßßßßßßßßßßßßßßßßßß³ßßßßßßßßßßßß³ßßßßßßßßÛÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞ²ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜܲ° Default NodeSpy Phone Book % °°°°°°°°°° ( /200) ° ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß - ENTER: Call ALT+E: Edit ALT+S: Sort INSERT: New DELETE: Remove \ No newline at end of file +ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜܲ System Name ²³² Address ²³² LastCall ²³² Calls ²Ûßßßßßßßßßßßßßßßßßßßßßßßßßßß³ßßßßßßßßßßßßßßßßßßßßßßßßßßßß³ßßßßßßßßßßßß³ßßßßßßßßÛÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞ²ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜܲ° Default NodeSpy PhoneBook ° ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + ENTER: Call ALT+E: Edit ALT+S: Sort DELETE: Clear ESCAPE: Quit \ No newline at end of file diff --git a/mystic/nodespy_ansiterm.pas b/mystic/nodespy_ansiterm.pas index cd78020..151b38d 100644 --- a/mystic/nodespy_ansiterm.pas +++ b/mystic/nodespy_ansiterm.pas @@ -2,8 +2,8 @@ Procedure DrawTerminalAnsi; Const IMAGEDATA_WIDTH=80; IMAGEDATA_DEPTH=25; - IMAGEDATA_LENGTH=1134; - IMAGEDATA : array [1..1134] of Char = ( + IMAGEDATA_LENGTH=1115; + IMAGEDATA : array [1..1115] of Char = ( #1,#16,'Ü','Ü',#25,#10, #8,'Ü','Ü',#25, #3, #7,'°', #0,#23,'²',#16, #25,#23, #9,#26, #4,'Ü',#25, #9,#14,'±','Û','±', #7,'°', #0,#23,'²', #16,#25, #8, #7,'°', #0,#23,'²', #8,#16,'g','j','!',#24,' ', #9,#17, @@ -62,15 +62,14 @@ Const 'M','Þ',#24,'Ý',#25,'M','Þ',#24, #7,'Ý',#25,'M','Þ',#24,'Ý',#25,'M', 'Þ',#24,'Ý',#25,'M','Þ',#24,#15,'Ý',#25,'M','Þ',#24, #7,'Ý',#25,'M', 'Þ',#24,#15,'Ý',#25,'M','Þ',#24,'Ý',#25,'M','Þ',#24,'²',#26,'M','Ü', - '²',#24, #7,'°',#23,' ', #0,'D','e','f','a','u','l','t',' ','N','o', - 'd','e','S','p','y',' ','P','h','o','n','e',' ','B','o','o','k',#25, - #27,'%',' ', #8,#16,#26, #9,'°',#23,' ', #0,'(',#25, #2,'/','2','0', - '0',')',' ', #7,#16,'°',#24,' ', #8,#26,'M','ß',#24,#25, #2,#15,'E', - 'N','T','E','R', #8,':',' ', #7,'C','a','l','l',#25, #3,#15,'A','L', - 'T','+','E', #8,':',' ', #7,'E','d','i','t',#25, #3,#15,'A','L','T', - '+','S', #8,':',' ', #7,'S','o','r','t',#25, #3,#15,'I','N','S','E', - 'R','T', #8,':',' ', #7,'N','e','w',#25, #3,#15,'D','E','L','E','T', - 'E', #8,':',' ', #7,'R','e','m','o','v','e',#24); + '²',#24, #7,'°',#23,#25,#26, #0,'D','e','f','a','u','l','t',' ','N', + 'o','d','e','S','p','y',' ','P','h','o','n','e','B','o','o','k',#25, + #25, #7,#16,'°',#24,' ', #8,#26,'M','ß',#24,#25, #2,#15,'E','N','T', + 'E','R', #8,':',' ', #7,'C','a','l','l',#25, #3,#15,'A','L','T','+', + 'E', #8,':',' ', #7,'E','d','i','t',#25, #3,#15,'A','L','T','+','S', + #8,':',' ', #7,'S','o','r','t',#25, #3,#15,'D','E','L','E','T','E', + #8,':',' ', #7,'C','l','e','a','r',#25, #3,#15,'E','S','C','A','P', + 'E', #8,':',' ', #7,'Q','u','i','t',#24); Begin Screen.LoadScreenImage(ImageData, ImageData_Length, ImageData_Width, 1, 1); -End; \ No newline at end of file +End; diff --git a/mystic/nodespy_common.pas b/mystic/nodespy_common.pas index 39962df..ed82d3d 100644 --- a/mystic/nodespy_common.pas +++ b/mystic/nodespy_common.pas @@ -105,8 +105,7 @@ Begin Until False; End; - If BoxType < 2 Then MsgBox.Close; - + MsgBox.Close; MsgBox.Free; Screen.CursorXY (SavedX, SavedY); diff --git a/mystic/nodespy_term.pas b/mystic/nodespy_term.pas index edb452e..9829531 100644 --- a/mystic/nodespy_term.pas +++ b/mystic/nodespy_term.pas @@ -4,65 +4,108 @@ Unit NodeSpy_Term; Interface +Procedure Terminal; + Implementation Uses + m_DateTime, m_Strings, m_FileIO, m_IniReader, + m_io_Base, + m_io_Sockets, + m_Term_Ansi, + m_MenuBox, + m_MenuForm, NodeSpy_Common; {$I NODESPY_ANSITERM.PAS} Type PhoneRec = Record - Name : String[40]; + Name : String[26]; Address : String[60]; User : String[30]; Password : String[20]; StatusBar : Boolean; + LastCall : String[8]; + Calls : String[5]; End; -Var - Book : Array[1..200] of PhoneRec; + PhoneBookRec = Array[1..100] of PhoneRec; -Procedure InitializeBook; Var - Count : Byte; + IsBookLoaded : Boolean; + +Function StripAddressPort (Str : String) : String; +Var + A : Byte; +Begin + A := Pos(':', Str); + + If A > 0 Then + StripAddressPort := Copy(Str, 1, A - 1) + Else + StripAddressPort := Str; +End; + +Function GetAddressPort (Addr : String) : Word; +Var + A : Byte; +Begin + A := Pos(':', Addr); + + If A > 0 Then + GetAddressPort := strS2I(Copy(Addr, A+1, Length(Addr))) + Else + GetAddressPort := 23; +End; + +Procedure InitializeBook (Var Book: PhoneBookRec); +Var + Count : SmallInt; Begin FillChar (Book, SizeOf(Book), 0); - For Count := 1 to 200 Do + For Count := 1 to 100 Do Begin Book[Count].StatusBar := True; + Book[Count].LastCall := '00/00/00'; + Book[Count].Calls := '0'; + End; - Book[1].Name := 'Mystic BBS Local Login'; + Book[1].Name := 'Local Login'; Book[1].Address := 'localhost:' + strI2S(Config.INetTNPort); End; -Procedure WriteBook; +Procedure WriteBook (Var Book: PhoneBookRec); Var OutFile : Text; Buffer : Array[1..4096] of Char; Count : SmallInt; Begin + ShowMsgBox (2, 'Saving phonebook'); + Assign (OutFile, 'nodespy.phn'); SetTextBuf (OutFile, Buffer); ReWrite (OutFile); - For Count := 1 to 200 Do Begin - WriteLn(OutFile, '[' + strI2S(Count) + ']'); - WriteLn(OutFile, #9 + 'name=' + Book[Count].Name); - WriteLn(OutFile, #9 + 'address=' + Book[Count].Address); - WriteLn(OutFile, #9 + 'user=' + Book[Count].User); - WriteLn(OutFile, #9 + 'pass=' + Book[Count].Password); - WriteLn(OutFile, #9 + 'statusbar=', Ord(Book[Count].StatusBar)); - WriteLn(OutFile, ''); + For Count := 1 to 100 Do Begin + WriteLn (OutFile, '[' + strI2S(Count) + ']'); + WriteLn (OutFile, #9 + 'name=' + Book[Count].Name); + WriteLn (OutFile, #9 + 'address=' + Book[Count].Address); + WriteLn (OutFile, #9 + 'user=' + Book[Count].User); + WriteLn (OutFile, #9 + 'pass=' + Book[Count].Password); + WriteLn (OutFile, #9 + 'statusbar=', Ord(Book[Count].StatusBar)); + WriteLn (OutFile, #9 + 'last=' + Book[Count].LastCall); + WriteLn (OutFile, #9 + 'calls=' + Book[Count].Calls); + WriteLn (OutFile, ''); End; Close (OutFile); End; -Procedure LoadBook; +Procedure LoadBook (Var Book: PhoneBookRec); Var INI : TIniReader; Count : SmallInt; @@ -71,28 +114,208 @@ Begin INI := TIniReader.Create('nodespy.phn'); - For Count := 1 to 200 Do Begin + INI.Sequential := True; + + For Count := 1 to 100 Do Begin Book[Count].Name := INI.ReadString(strI2S(Count), 'name', ''); Book[Count].Address := INI.ReadString(strI2S(Count), 'address', ''); Book[Count].User := INI.ReadString(strI2S(Count), 'user', ''); Book[Count].Password := INI.ReadString(strI2S(Count), 'pass', ''); Book[Count].StatusBar := INI.ReadString(strI2S(Count), 'statusbar', '1') = '1'; + Book[Count].LastCall := INI.ReadString(strI2S(Count), 'last', ''); + Book[Count].Calls := INI.ReadString(strI2S(Count), 'calls', ''); End; INI.Free; End; -Procedure Terminal; +Procedure TelnetClient (Dial: PhoneRec); +Const + BufferSize = 1024 * 4; +Var + Client : TIOSocket; + Res : LongInt; + Buffer : Array[1..BufferSize] of Char; + Done : Boolean; + Ch : Char; Begin - If Not FileExist('nodespy.phn') Then Begin - ShowMsgBox(2, 'Creating phone book'); + ShowMsgBox (2, 'Connecting to ' + Dial.Address); - InitializeBook; - WriteBook; - End Else - LoadBook; + Client := TIOSocket.Create; - DrawTerminalAnsi; + Client.FTelnetClient := True; + + If Not Client.Connect(StripAddressPort(Dial.Address), GetAddressPort(Dial.Address)) Then + ShowMsgBox (0, 'Unable to connect') + Else Begin + Screen.TextAttr := 7; + Screen.ClearScreen; + + Done := False; + Term := TTermAnsi.Create(Screen); + + If Dial.StatusBar Then Begin + Screen.SetWindow (1, 1, 80, 24, True); + Screen.WriteXY (1, 25, Config.StatusColor3, strPadC('ALT-X/Quit', 80, ' ')); + End; + + Term.SetReplyClient(TIOBase(Client)); + + Repeat + If Client.DataWaiting Then Begin + Res := Client.ReadBuf (Buffer, BufferSize); + + If Res < 0 Then Begin + Done := True; + Break; + End; + + Term.ProcessBuf(Buffer, Res); + End Else + If Keyboard.KeyPressed Then Begin + Ch := Keyboard.ReadKey; + + Case Ch of + #00 : Case Keyboard.ReadKey of + #45 : Break; + #71 : Client.WriteStr(#27 + '[H'); + #72 : Client.WriteStr(#27 + '[A'); + #73 : Client.WriteStr(#27 + '[V'); + #75 : Client.WriteStr(#27 + '[D'); + #77 : Client.WriteStr(#27 + '[C'); + #79 : Client.WriteStr(#27 + '[K'); + #80 : Client.WriteStr(#27 + '[B'); + #81 : Client.WriteStr(#27 + '[U'); + #83 : Client.WriteStr(#127); + End; + Else + Client.WriteBuf(Ch, 1); + + If Client.FTelnetEcho Then Term.Process(Ch); + End; + End Else + WaitMS(10); + Until Done; + + Term.Free; + End; + + Client.Free; + + Screen.TextAttr := 7; + Screen.SetWindow (1, 1, 80, 25, True); End; -End. \ No newline at end of file +Procedure EditEntry (Var Book: PhoneBookRec; Num: SmallInt); +Var + Box : TMenuBox; + Form : TMenuForm; + NewRec : PhoneRec; +Begin + NewRec := Book[Num]; + Box := TMenuBox.Create(Screen); + Form := TMenuForm.Create(Screen); + + Box.Header := ' Book Editor '; + + Box.Open (18, 8, 63, 16); + + Form.AddStr ('N', ' Name' , 24, 10, 32, 10, 6, 26, 26, @NewRec.Name, ''); + Form.AddStr ('A', ' Address', 21, 11, 32, 11, 9, 30, 60, @NewRec.Address, ''); + + Form.Execute; + + If Form.Changed Then + If ShowMsgBox(1, 'Save changes?') Then Begin + Book[Num] := NewRec; + WriteBook(Book); + End; + + Form.Free; + + Box.Close; + Box.Free; +End; + +Function GetTerminalEntry (Var Book: PhoneBookRec; Var Dial: PhoneRec) : Boolean; +Var + Count : SmallInt; + List : TMenuList; +Begin + Result := False; + + If Not FileExist('nodespy.phn') Then Begin + ShowMsgBox (2, 'Creating phone book'); + WriteBook (Book); + + IsBookLoaded := True; + End Else + If Not IsBookLoaded Then Begin + LoadBook(Book); + IsBookLoaded := True; + End; + + DrawTerminalAnsi; + + Repeat + List := TMenuList.Create(Screen); + + List.NoWindow := True; + List.AllowTag := False; + List.LoAttr := 7; + List.HiAttr := 9 + 1 * 16; + List.LoChars := #13#27; + List.HiChars := #18; + + For Count := 1 to 100 Do + List.Add(strPadR(Book[Count].Name, 26, ' ') + ' ' + + strPadR(Book[Count].Address, 26, ' ') + ' ' + + Book[Count].LastCall + ' ' + + strPadL(Book[Count].Calls, 6, ' '), + 2); + + List.Open(1, 12, 80, 22); + + Case List.ExitCode of + #13 : If Book[List.Picked].Address = '' Then + ShowMsgBox(0, 'Address is empty') + Else Begin + With Book[List.Picked] Do Begin + LastCall := DateDos2Str(CurDateDos, 1); + Calls := strI2S(strS2I(Calls) + 1); + End; + + WriteBook(Book); + + Dial := Book[List.Picked]; + Result := True; + + Break; + End; + #18 : EditEntry(Book, List.Picked); + #27 : Break; + End; + + List.Free; + Until False; +End; + +Procedure Terminal; +Var + Dial : PhoneRec; + Book : PhoneBookRec; +Begin + Screen.SetWindowTitle('NodeSpy/Terminal'); + + InitializeBook(Book); + + IsBookLoaded := False; + + Repeat + If Not GetTerminalEntry(Book, Dial) Then Break; + + TelnetClient(Dial); + Until False; +End; + +End.