#!/usr/local/bin/kermit + # # i k s d p y -- IKSD display # # Active display of IKSD database. # Main screen lists all sessions, with option to switch to # a per-session detail screen. # # Illustrates: # . File record i/o # . WAIT FILE and \v(kbchar) # . Arithmetic # . Hexadecimal decoding # . Single-keystroke program control # . Compact substring notation # . Rudimentary screen formatting # # Requires: C-Kermit 7.0 Beta.11 or later. # # Last update: Tue Dec 7 19:19:03 1999 # Documentation: iksdb.txt # # Author: F. da Cruz, Columbia University, November 1999. local \%c \%n \%p block dbfile rate dir user info ; Configuration (change as needed)... .rate = 4 ; Screen refresh rate (sec) if def \%1 .dbfile := \%1 ; Database file if not def dbfile { if eq "\v(platform)" "32-bit_Windows" { if not equal "\$(winbootdir)" "" .dbfile := \$(winbootdir)/iksd.db else if not equal "\$(windir)" "" .dbfile := \$(windir)/iksd.db else if not equal "\$(SystemRoot)" "" .dbfile := \$(SystemRoot)/iksd.db else .dbfile = c:/iksd.db } else { .dbfile = /var/log/iksd.db } } ; Operating variables and settings... set case off ; Case matters not set quiet on ; No noisy messages set sleep cancel on ; Allow interrupt WAIT from keyboard ; Macros define SHOWHELP { ; Main help screen cls echo {IKSD Display...} echo echo {Press:} echo { The Space Bar to switch between summary and detail screens.} echo { A digit to view a particular session, 0 through 9, or:} echo { X to enter a session number with two or more digits.} echo { M to return to the Main screen.} echo { N to see the Next session (cycle through sessions).} echo { H to see this Help message.} echo { Q to Quit.} set ask-timer 0 echo getc \%9 {Press any key to continue: } set ask-timer \m(rate) } define SHOWRECORD { ; Interpret a record .pid := \fltrim(\s(block[17:16]),0) .flags := \fhex2n(\s(block[1:4])) if ( (\m(flags)&1) ) { .\%v = (IN_USE) } else { .\%v = (FREE) } if ( (\m(flags)&2) ) { .\%v := \%v(REAL_USER) } if ( (\m(flags)&4) ) { .\%v := \%v(LOGGED_IN) } cls ; Clear screen and print detail echo [\m(dbfile)] Session \%1: \v(time)... echo echo { Flags: \s(block[1:4]) \%v} echo { AuthT: \s(block[5:4])} echo { AuthM: \s(block[9:4])} echo { State: \s(block[13:4])} echo { Lhost: \fhex2ip(\s(block[41:8]))} ; 32+8+1 echo { Rhost: \fhex2ip(\s(block[57:8]))} ; 48+8+1 echo { PID: \m(pid) (\fhex2n(\m(pid)))} echo { Start: \s(block[66:17])} echo { Last: \s(block[84:17])} echo { User: \s(block[1025:\fhex2n(\s(block[101:4]))])} echo { Dir: \s(block[2049:\fhex2n(\s(block[105:4]))])} echo { Info: \s(block[3073:\fhex2n(\s(block[109:4]))])} echo } define SHOWDETAIL { ; Show details for a session local \%k \%v \%x if not def \%1 return if ( < \fcode({\%1}) 32 ) return if eq {\%1} { } .\%1 = 0 if eq {\%1} {N} .\%1 = 0 .\%x = \%1 while true { ; Loop in detail screen if def \%x switch \%x { ; What did they type? :[0-9] ; A digit .\%1 := \%x break ; So that's the session number. :H, showhelp, ; An 'H' so show help text. if not num \%1 return break :Q, echo Q, exit 0 ; 'Q' for quit. :N, .\%n ::= (\fsize(\m(dbfile))/4096) ; Check for new records .\%1 ::= \fmod(\%1+1,\%n) ; Go to next session break :X, xecho \13 ; Long session number screen cleol ; Clear this line set ask-timer 0 ask \%1 { Enter session number: } ; Prompt and wait for text set ask-timer \m(rate) ; up to CR with no timeout. if not def \%1 .\%1 = 0 ; If CR only, use 0. if not numeric \%1 { ; Check for n-ness. echo Number required return } break :M, return ; Return to main screen. :default echo Not a choice: "\%1" pause 1 return } if ( > \%1 (\%n-1) || < \%1 0 ) { echo Out of range, pause 1, return } .\%k ::= \%1*4096 ; Seek position for desired record fclose \%c ; Close/Open to force data refresh fopen /read /binary \%c \m(dbfile) if fail end 1 CLOSE OPEN FAILURE fseek \%c \%k ; Seek to record if fail end 1 Seek failed. .\%p := \f_pos(\%c) fread /size:4096 \%c block ; Read it if fail end 1 Read failed. if ( ! = \f_pos(\%c) \%p+4096 ) exit 1 FATAL - Database corrupt showrecord \%1 ; Show it xecho {[0-9] (session digit), H[elp], or Q[uit]: } wait 60 file modification \m(dbfile) if success continue undef \%x if ( def \v(kbchar) ) { .\%x := \v(kbchar) } else { getc \%x } if not def \%x continue if eq { } {\%x} .\%x = M } } ; Main display... undef \%c ; Database not yet open set ask-timer \m(rate) ; Refresh rate control while true { ; Main loop cls if ( not def \%c ) { ; If database not open if exist \m(dbfile) { ; If it exists fopen /read /binary \%c \m(dbfile) ; Open it if fail { echo \m(dbfile) - Open failed: \f_errmsg() sleep \m(rate) continue } } else { ; It doesn't exist echo [\m(dbfile)] - Does not exist: \v(time)... sleep \m(rate) continue } } echo [\m(dbfile)] \v(time)... ; Top line - filename & time echo echo { Flgs Host........... Start... Last.... (PID)(user)(dir)(what)} .\%n = 0 frewind \%c ; Rewind database if fail { undef \%c, continue } ; On failure go gack and reopen it while ( ! \f_eof(\%c) ) { ; Loop to read each record fread /size:4096 \%c block if fail break if ( != \fmod(\f_pos(\%c),4096) 0 ) exit 1 FATAL - Database corrupt incr \%p 4096 .user := \ftrim(\s(block[1025:1024])) .dir := \ftrim(\s(block[2049:1024])) .info := \ftrim(\s(block[3073:1024])) .\%a := \flpad(\%n,2). \s(block[1:4]) - \frpad(\fhex2ip(\s(block[57:8])),15)\s(block[74:9])\s(block[92:9]) - (\fhex2n(\s(block[17:16])))(\m(user))(\m(dir))(\m(info)) echo \fleft(\%a,\v(cols)) incr \%n } echo xecho {[0-9] (session digit), H[elp], or Q[uit]: } wait 60 file modification \m(dbfile) if success continue undef \%x if ( def \v(kbchar) ) { .\%x := \v(kbchar) } else { getc \%x } if ( defined \%x ) showdetail {\%x} if ( == \%n 1 ) { fclose \%c, undef \%c } ; Force refresh if only one }