| #!/usr/bin/expect |
| # Copyright 2000, 2001, 2004 by Paul Mattes. |
| # Permission to use, copy, modify, and distribute this software and its |
| # documentation for any purpose and without fee is hereby granted, |
| # provided that the above copyright notice appear in all copies and that |
| # both that copyright notice and this permission notice appear in |
| # supporting documentation. |
| # |
| # s3270 is distributed in the hope that it will be useful, but WITHOUT ANY |
| # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| # FOR A PARTICULAR PURPOSE. See the file LICENSE for more details. |
| # |
| # Based on cms_cmd.expect licenced as above, modifications generating |
| # zseries-console: |
| # (C) Copyright IBM Corp. 2004, 2005, 2006 |
| # and released under the GNU Public License V2 |
| # |
| |
| # Read in the glue functions. |
| set lib [file dirname $argv0] |
| source "$lib/x3270_glue.expect" |
| |
| set P "console-zseries" |
| |
| if { [llength $argv] != 4 } { |
| puts stderr "Usage: $P <VM Userid> <VM Password> zseries <VM System>" |
| exit 1 |
| } |
| |
| set username [lindex $argv 0] |
| set password [lindex $argv 1] |
| set hostname [lindex $argv 3] |
| set command "ipllnx" |
| |
| # Procedure to wait for a READ prompt from CMS or CP. |
| proc waitread {} { |
| Snap Save |
| while {[Snap Ascii [expr [Snap Rows]-1] [expr [Snap Cols]-17] 4] |
| != "Read"} { |
| Snap Wait Output |
| } |
| } |
| |
| # Procedure to check for the CMS "Ready" prompt. |
| # Returns its row number, or -1 for "MORE..." state, and leaves a screen with |
| # data to read in the Snap buffer. |
| proc cmd_done {} { |
| global verbose |
| Snap Save |
| while {1} { |
| if {[Snap Ascii [expr [Snap Rows]-1] [expr [Snap Cols]-20] 7] |
| == "More..."} { |
| if {$verbose} {puts "More..."} |
| return -1 |
| } |
| |
| set i [expr [Snap Rows]-2] |
| while {$i >= 0} { |
| set text [Snap Ascii $i 0 [Snap Cols]] |
| switch -regexp -- $text { |
| "Ready; T=.*" {return $i} |
| "Ready\(.*\); T=.*" { |
| error [Snap Ascii [expr $i-1] 0 \ |
| [Snap Cols]] |
| } |
| "^ *\$" {} |
| "00: Please choose*" { return $i } |
| default { |
| if {$verbose} { |
| #puts "Incomplete $i '[string trimright $text]'" |
| } |
| set mylength [string length [string trimright $text]] |
| if { $mylength > 5 } { |
| if {[Snap Ascii $i [expr $mylength-6] 6] == "login:"} { |
| puts "Hohooooooooo login prompt found" |
| return $i |
| } |
| } |
| |
| set i 0 |
| } |
| } |
| incr i -1 |
| } |
| Snap Wait Output |
| } |
| } |
| |
| # Execute a command, return the output. |
| proc cms_cmd {text} { |
| global verbose |
| |
| # Clear the screen. |
| Clear |
| |
| # Send the command. |
| String "$text\n" |
| |
| # 'first' is the row where the first line of output will appear. For |
| # the first screenful it's 1; after that it's 0. |
| set first 1 |
| |
| # r is the result. |
| set r {} |
| |
| while {1} { |
| # Wait for a screenful. |
| set d [cmd_done] |
| |
| # Dump out what's there. |
| set i $first |
| #set first 0 |
| if {$d < 0} {set last [expr [Snap Rows]-2]} {set last $d} |
| |
| while {$i <= $last} { |
| set r [linsert $r end [string trimright [Snap Ascii $i 0 [Snap Cols]]]] |
| incr i |
| } |
| if {$d >= 0} { |
| for {set n 0} {$n < [llength $r]} {incr n} { |
| puts [lindex $r $n] |
| } |
| break |
| } |
| |
| # Clear the screen and go around again. |
| Clear |
| } |
| return $r |
| } |
| |
| ## Calculates how many lines are there in the s3270 screen buffer |
| proc find_last_line {} { |
| global debug |
| global verbose |
| Snap Save |
| |
| if {$debug == 1} { |
| puts "v---" |
| foreach l [Snap Ascii] { |
| puts $l |
| } |
| puts "^---" |
| } |
| |
| if {[Snap Ascii [expr [Snap Rows]-1] [expr [Snap Cols]-20] 7] |
| == "More..."} { |
| ## To denote the console buffer is full |
| return -1 |
| } |
| |
| set i [expr [Snap Rows]-3] |
| |
| while {$i >= 0} { |
| set text [Snap Ascii $i 0 [Snap Cols]] |
| switch -regexp -- $text { |
| "^ *\$" { |
| } |
| default { |
| return $i |
| } |
| } |
| incr i -1 |
| } |
| ## To denote the console buffer is empty |
| return -2 |
| } |
| |
| # Print the s3270 screen buffer |
| proc print_cons_buf {} { |
| ##puts "<<output>>" |
| set output 0 |
| while {1} { |
| # Grab the screen and clear it out. |
| Snap Save |
| Clear |
| |
| set screen [Snap Ascii 0 0 [expr [Snap Rows]-3] [Snap Cols]] |
| |
| # Find how many lines are populated and output those. |
| for {set last [llength $screen]} {$last >= 0} {incr last -1} { |
| switch -regexp -- [lindex $screen $last] { |
| "^ *\$" { |
| } |
| default { |
| break |
| } |
| } |
| } |
| ##puts "last<$last>" |
| if {$last < 0} { |
| break |
| } |
| for {set line 0} {$line <= $last} {incr line} { |
| set output 1 |
| puts -nonewline "\n[string trimright [lindex $screen $line]]" |
| } |
| } |
| ##puts "output<$output>" |
| return $output |
| } |
| |
| # Set 'verbose' to 1 to get debug output from the glue functions. |
| set verbose 1 |
| set debug 0 |
| |
| proc note {m} { |
| global P |
| puts "$P: $m" |
| } |
| proc warn {m} { |
| global P |
| puts "$P: WARNING: $m" |
| } |
| proc winge {m} { |
| global P |
| puts "$P: MACHINE ERROR: reboot failed - $m" |
| } |
| |
| note "Logging into the hosting VM system to restart the VM guest" |
| |
| # Start s3270 |
| Start |
| # Setverbose 1 |
| |
| # Connect to the host and wait for an input field. |
| Connect $hostname |
| Wait InputField |
| |
| # Log in and wait for CP READ or VM READ mode. |
| note "logging in ... sending username" |
| String "$username\n" |
| |
| # Wait for the input field, to proceed further. If timed out screen scrape |
| # the s3270 (error) message. |
| if {[catch {set ret_val [Wait 10 InputField]} err]} { |
| print_cons_buf |
| note "password never prompted" |
| exit 2 |
| } |
| |
| # Sometimes the input field is emitted before the output from the VMserver. |
| # Hence, after reading the input field wait for the output. |
| if {[catch {set ret_val [Wait 10 Output]} err]} { |
| print_cons_buf |
| note "No output seen even after the reading the InputFiled" |
| exit 2 |
| } |
| |
| if { [Ascii 2 0 19 ] == "Enter your password" } { |
| print_cons_buf |
| note "pasword prompted ..." |
| note "sending password ..." |
| String "$password\n" |
| } elseif { [Ascii 1 11 7] == "Already"} { |
| # If we can't log on, we're hosed. |
| Enter |
| print_cons_buf |
| warn "Already logged in. logging in here....." |
| String "logon $username here\n" |
| # Wait for the input field to proceed further |
| if {[catch {set ret_val [Wait 10 InputField]} err]} { |
| print_cons_buf |
| note "password never prompted" |
| exit 2 |
| } |
| if { [Ascii 2 0 19 ] == "Enter your password"} { |
| print_cons_buf |
| note "sending password ..." |
| String "$password\n" |
| } |
| } elseif { [Ascii 1 20 19] == "not in CP directory" } { |
| print_cons_buf |
| note "'$username' is not a valid username" |
| exit 1 |
| } else { |
| # Other unknown errors (firewall??) |
| print_cons_buf |
| warn "Unknown Error: Check the console log" |
| exit 1 |
| } |
| |
| if { [Ascii 1 11 23] == "PASSWORD NOT AUTHORIZED" } { |
| while {1} { |
| note "authorisation failure: PASSWORD NOT AUTHORIZED: holding ..." |
| after 5000 |
| } |
| exit 1 |
| } elseif { [Ascii 1 11 16] == "PASSWORD EXPIRED" } { |
| while {1} { |
| note "authorisation failure: PASSWORD EXPIRED: holding ..." |
| after 5000 |
| } |
| note "Password expired" |
| exit 1 |
| } { |
| note "Password authorized" |
| } |
| print_cons_buf |
| waitread |
| |
| note "Connected to VM" |
| |
| # If we're in CP mode, which means we disconnected last time, boot CMS. |
| if {[Ascii [expr [Rows]-1] [expr [Cols]-20] 2] == "Cp"} { |
| note "Starting CMS" |
| Clear |
| String "i cms\n" |
| String "no" |
| waitread |
| } |
| |
| Snap save |
| set n [expr [Snap Rows]-2] |
| set first 1 |
| while {$n >= $first} { |
| set lptext [Snap Ascii $first 0 [Snap Cols]] |
| set lplength [string length [string trimright $lptext]] |
| puts "$lptext " |
| incr first |
| } |
| |
| # Enter an empty command to get a CMS prompt. If we don't do this, there will |
| # be a Ready prompt as the first line of output below. |
| Enter |
| cmd_done |
| |
| note "Executing command $command" |
| cms_cmd $command |
| Clear |
| |
| String "#cp term more 50 10\n" |
| |
| set timeouts {1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 5} |
| set otimeout 0 |
| set double 1 |
| set cmdline {} |
| while {1} { |
| set ctimeout $otimeout |
| interact { |
| "" { |
| puts -nonewline "\b \b" |
| set cmdline [string range $cmdline 0 end-1] |
| flush stdout |
| } |
| "" { |
| puts -nonewline "\b \b" |
| set cmdline [string range $cmdline 0 end-1] |
| flush stdout |
| } |
| "\r" { |
| ## When enter(alone) is pressesed, s3270 goes from |
| ## "Running" to "Vm Read" mode. So, for actual one |
| ## enter key press, two 'Enter'[a s3270 function] is |
| ## required |
| String $cmdline |
| set cmdline {} |
| Enter |
| if {$double == 1} { |
| Enter |
| } |
| set double 1 |
| |
| print_cons_buf |
| if {$ctimeout != 0} { |
| set otimeout 0 |
| return |
| } |
| } |
| -re "(.)" { |
| set char $interact_out(0,string) |
| puts -nonewline "$char" |
| set cmdline "$cmdline$char" |
| flush stdout |
| set double 0 |
| |
| if {$ctimeout != 0} { |
| set otimeout 0 |
| return |
| } |
| } |
| timeout [lindex $timeouts $otimeout] { |
| ## Read the console buffer and print it |
| ##puts "<<timeout>>" |
| if {[print_cons_buf]} { |
| set otimeout 0 |
| } elseif {$otimeout < 15} { |
| incr otimeout |
| } |
| |
| #puts "TIMEOUT: $otimeout [lindex $timeouts $otimeout]" |
| return |
| } |
| } |
| } |