#!/usr/local/bin/kermit + # # m o d e m t e s t 2 # # Modem test and statistics -- Works on Windows, UNIX, and VMS. # # Requires C-Kermit 7.1 # F. da Cruz, Columbia University, Feb 2001 # # Sometimes it's easier to hardwire the parameters... # .device = com1 .modem = usr .speed = 115200 ; For USR v.34 use 57600 and for V.90 use 115200 .origin = 212-316-3982 .\%1 = watsun .\%2 = fdc .\%3 = test.zip ; Note: phone numbers are fake dcl \&n[] = 5551234 5551235 5551236 5551237 5551238 5551239 5551240 - 5551241 5551242 5551243 5551244 5551245 5551246 5551247 ; Array of terminal server names dcl \&p[] = ccts1 ccts2 ccts3 ccts4 ccts5 ccts6 .\%n := \fdimension(&n) ; Number of numbers ; Array of terminal server prompts (= name with ">" appended) dcl \&q[\fdim(&p)] for \%i 1 \fdim(&p) 1 { .\&q[\%i] := \&p[\%i]> } ; This script takes great care to recover from errors so it can run ; unattended for long periods of time and to record whatever data it got ; on each run even if the session terminated prematurely. ; ; As written, this script assumes a Cisco terminal server that has a ; "terminal autohangup" command. SET CARRIER-WATCH is OFF at first, so we ; can query and then dial the modem. After successful dialing, we set it ; ON so we can catch disconnections promptly. We also send "terminal ; autohangup" to the Cisco so when the host session terminates (as it ; should when we send it a BYE command), the terminal server hangs up the ; modem. All i/o's are tested for success or failure. Once the data ; transfer phase is complete, we SET CARRIER-WATCH OFF again so we can ; query the modem for stats. ; ; Modem queries are supported for US Robotics and Compaq modems, and ; tested with USR V.34 and "V.Everything" 56K, and Compaq Presario 56K-DF. ; define badversion echo C-Kermit 7.1 or K95 1.1.21 or later required, exit if LLT \v(version) 701199 badversion if not def \v(buildid) badversion if LLT \v(buildid) 20001116 badversion ; local model firmware \%i \%j ; local debug retrains blers ispeed ospeed ; local user pass host file upcps dncps head tsport seq ; Configuration parameters -- change as needed (*) ;; LOG SESSION session.log append ; (*) uncomment for extra debugging SET DIAL TIMEOUT 30 SET SEND TIMEOUT 6 FIXED SET INPUT BUFFER-LENGTH 10240 .debug = 1 ; (*) Change to 0 for minimal messages .logfile = modem.log ; (*) Log file name switch \v(system) { ; Device and modem defaults... :win32 ; For Windows 95/98/NT/2000 if not def device .device = tapi ; (*) Change if necessary if not def modem .modem = tapi ; (*) Ditto if not def speed .speed = 115200 ; (*) Port speed - change if necessary break :unix ; For UNIX... if not def device .device = /dev/cua ; (*) Change to your dialout device if not def modem .modem = usrobotics ; (*) Change to match your modem if not def speed .speed = 115200 ; (*) Port speed - change if necessary break :vms ; For VMS... if not def device .device = TTA0: ; (*) Change to your dialout device if not def modem .modem = usrobotics ; (*) Change to match your modem if not def speed .speed = 57600 ; (*) Port speed - change if necessary break :default ; Add others here... exit 1 Sorry - this script does not run on \v(platform). } if not def origin .origin = UNKNOWN .model = UNKNOWN ; Modem model .firmware = UNKNOWN ; Modem firmware if def \%1 .host := \%1 ; Accept host, user, and filename if def \%2 .user := \%2 ; from command line (UNIX only) if def \%3 .file := \%3 ; or from TAKE command line. ; Macro definitions def usrinfo { ; Get info about USR modem ; If we weren't cheating we'd do ATI6 and parse the results. ; See usrgetstats for a non-cheating example. ; Meanwhile change the strings to match your own modem. if eq "\v(speed)" "115200" { .model = USRobotics Courier V.Everything V.90 .firmware = 7.3.14 / 3.0.13 } else { .model = USRobotics Courier V.32bis V.34+ Fax .firmware = 6.2.3 / 1.2.4 } } def cpqinfo { ; Get info about Compaq modem ; If we weren't cheating we'd do ATI and parse the results. ; See cpqgetstats for a non-cheating example. ; Meanwhile change the strings to match your own modem. .model = Compaq Presario 56K-DF .firmware = 1.3.12 } def getmdminfo { ; Get modem info. switch \v(modem) { :usrobotics usrinfo, break :tapi :compaq cpqinfo, break } } ; Get and parse a statistics report from a USR modem. ; This version parses the report on the fly. def usrstats { ; Get USR connection statistics. local \%x \%y \%z clear input output ATI6\13 ; Send ATI6 and parse output. set flag off set input echo on while not flag { minput 10 Blers Retrains Speed OK switch \v(minput) { :1, clear input, input 2 \10, .blers := \fword(\v(input),1), break :2, clear input, input 2 \10, .retrains := \fword(\v(input),5), break :3, clear input, input 2 \10, .ospeed := \fword(\v(input),1,,/), break :4, set flag on, break } } } ; Get and parse a statistics report from a USR modem. ; This version (which works but is not used) reads the whole report at ; once and parses it afterwards. The Compaq report parser (next macro) ; also uses this method. def xusrstats { ; Get USR connection statistics. local \%x \%y \%z clear input output ATI6\13 ; Send ATI6 and parse output. input 20 OK if fail end 1 .\%x := \findex(Retrains Granted,\v(input)) if \%x .retrains := \fword(\fsubstr(\v(input),\%x),3) .\%x := \findex(Blers,\v(input),\%x+16) if \%x .blers := \fword(\fsubstr(\v(input),\%x),2) .\%x := \findex(Speed,\v(input),\%x+16) if \%x .ospeed := \fword(\fsubstr(\v(input),\%x),2,,/) } ; Get and parse a statistics report from a Compaq modem. ; This version reads the whole report at once and parses it afterwards. def cpqstats { ; Get Compaq connection statistics. local \%x \%y \%z clear input output ATI11\13 ; Send ATI11 and parse output. if fail end 1 input 6 ESC to quit. if fail end 1 output {\32} ; Tickle "press any key to continue" minput 20 OK {NO CARRIER} if fail end 1 .\%x := \findex(Final Transmit Carrier Rate,\v(input)) if \%x .\%y := \fword(\fsubstr(\v(input),\%x),5) .\%x := \findex(Final Receive Carrier Rate,\v(input)) if \%x .\%z := \fword(\fsubstr(\v(input),\%x),5) if \%x .ospeed := \%y/\%z .\%x := \findex(Receive Frame Error Count,\v(input)) if \%x .blers := \fword(\fsubstr(\v(input),\%x),5) .\%x := \findex(Retrain by Local Modem,\v(input)) if \%x .retrains := \fword(\fsubstr(\v(input),\%x),5) } def getmdmstats { ; Get modem connection statistics. switch \v(modem) { :usrobotics usrstats, break :tapi :compaq cpqstats, break } } def openlog { ; Open the log file and write heading fopen /append \%c \m(logfile) if fail exit 1 Can't open log "\m(logfile)" fwrite \%c fwrite \%c {Time: \v(date) \v(time)} fwrite \%c {Platform: \v(platform)} fwrite \%c {Software: \v(xprogram) \v(xversion)} fwrite \%c {Modem: \m(model)} fwrite \%c {Firmware: \m(firmware)} fwrite \%c {Interface Speed: \m(speed)} fwrite \%c {Calling from: \m(origin)} fwrite \%c {Log File: \m(logfile)} fwrite \%c {Test File: \m(file)} fwrite \%c {Test File Size: \fsize(\m(file))} fwrite \%c fwrite /string \%c {Date Time Number Line Speed Speed-After } fwrite \%c {Blers Retr Upload Dnload} fwrite /string \%c {---------- ------- -------- ----- ----------- } fwrite \%c {----- ---- ------ ------} fclose \%c } define logrecord { ; Write a log entry if \f_status(\%c) fclose \%c fopen /append \%c \m(logfile) if fail exit 1 LOG OPEN FAILURE: "\m(logfile)" fwrite \%c {\m(head) \%1} if fail exit 1 LOG WRITE FAILURE: "\m(logfile)" fclose \%c if \m(debug) { echo, echo {\m(head) \%1} } } define dologin { ; Login from terminal server to host output telnet \m(host)\13 ; and start Kermit in server mode there. input 40 login: if fail end 1 out \m(user)\13 input 20 Password: if fail end 1 out \m(pass)\13 input 90 {$ } output kermit -x\13 input 60 READY TO SERVE... if fail end 1 } def xmsg { ; Send message to file transfer display if not def \v(buildid) end if llt \v(buildid) 20001116 end set xfer message \m(seq): \v(dialnumber) (\m(tsport)) \v(time) } def doio { ; Transfer a file back & forth local rc ; and get performance statistics .rc = 1 while exist \m(file) { remote cd /tmp if fail break remote set file collision overwrite do xmsg send \m(file) delete.me if fail break .upcps := \v(cps) do xmsg get delete.me if fail break .dncps := \v(cps) .rc = 0 break } if not open connection end 1 bye end \m(rc) } ; End of macro definitions while not def host { ; Get hostname ask host { Host: } ; if not given on command line... } while not def user { ; Ditto for username... ask user { User: } } while not def pass { ; Always prompt for password. askq pass { Password: } } while not def file { ; Get filename if not given ask file { File to transfer: } ; on command line. if exist \m(file) break echo \m(file) not found. } if not equal "\m(device)" "tapi" { ; Except in K95... set modem type \m(modem) ; Specify modem type if fail { ; Check for error exit 1 {Error: Modem type "\m(modem)" not known} } } set carrier off ; Don't require carrier yet set line \m(device) ; Open the device if fail { ; Check for failure exit 1 {Error: \m(device) not available} } set speed \m(speed) ; Set the desired speed getmdminfo ; Get modem info set xfer bell off ; Turn off annoying bell if \m(debug) { ; Echo parameters for this run... echo { Device: \m(device)} echo { Speed: \m(speed)} echo { Modem: \m(modem)} echo { Model: \m(model)} echo { Firmware: \m(firmware)} echo { Host: \m(host)} echo { User: \m(user)} echo { Password: \frepeat(*,\flen(\m(pass)))} echo { File: \m(file)} echo { Size: \fsize(\m(file))} set modem speaker on set dial display on set input echo on set xfer display full } else { set modem speaker off set dial display off set input echo off set quiet on set xfer display brief } ; Device is open... set dial retries 0 ; No redialing set dial speed-matching off ; No speed changing def on_exit hangup ; In case of Ctrl-C set exit warning off ; In case of misconfigured modem set file collision overwrite ; Don't pile up lots of backup files set bell off ; Silence please if \m(debug) show comm openlog ; Start logging .seq = 0 ; Call number while true { ; Loop till user types something for \%i 1 \%n 1 { ; Call each phone number incr seq ; Count this call .status = ERRORS ; Assume there will be errors (for msg) set carrier off ; For dialing .\%9 := \fcvtdate(\v(date) \v(time)) .date := \fsubstr(\%9,5,2)/\fsubstr(\%9,7,2) .time := \fsubstr(\%9,10,2)\fsubstr(\%9,13,2) .head := \m(date) \m(time) \&n[\%i] clear dial-status dial \&n[\%i] if fail { switch \v(dialstatus) { :8, logrecord {FAILED: Timed out}, break :9, logrecord {FAILED: User canceled}, stop :10, logrecord {FAILED: Modem not ready}, break :default, logrecord {FAILED: "\v(dialresult)"}, break } continue } set carrier on ; For logging in and file transfer .ispeed := \fword(\v(dialresult),2) ; Speed from CONNECT message clear input .\%x := 0 for \%j 1 10 1 { ; Get terminal server herald output \13 xecho {#} minput 10 \fjoin(&q,,2) if success break } if > \%j 10 { logrecord {FAILED: No terminal server prompt} continue } .tmp := \v(input) .\%x = \v(minput) .\%y = \findex({\&p[\%x] line },\m(tmp)) .tsport = UNK if > \%y 0 { .tsport := \flpad(\fword(\s(tmp[\%y]),3),3,0) } .server := \&p[\%x] .tsport := \m(server):\m(tsport) .head := \m(head)\flpad(\m(tsport),12) .upcps = FAILED .dncps = FAILED lineout term autohangup minput 6 \fjoin(&q,,2) if success { dologin if success doio if success .status = OK } pause 1 set carrier off ; For getting modem statistics hangup ; Hang up modem but don't close pause 1 .retrains = UNK .blers = UNK .ospeed = UNKNOWN output AT\13 ; Make sure we're in command mode. input 3 OK if success getmdmstats ; We are - Get statistics from modem. .\%7 := \flpad(\m(ispeed),5)\flpad(\m(ospeed),13) .\%8 := \flpad(\m(blers),6) \flpad(\m(retrains),4) .\%9 := \flpad(\m(upcps),6) \flpad(\m(dncps),7) logrec {\%7 \%8 \%9} ; Write log record set ask-timer 5 echo echo {----------------------------------------} echo PASS \m(seq) DONE (\m(status))... clear keyboard-buffer getc \%j {PRESS ANY KEY WITHIN 5 SECONDS TO QUIT: } echo {----------------------------------------} if not asktimeout stop set ask-timer 0 echo echo Continuing... } } exit