1#!/usr/bin/expect 2 3# This file provides many valuable expect procedures like handle_timeout and 4# handle_eof. 5 6my_source [list print.tcl] 7 8 9proc handle_timeout { description } { 10 11 # Print timeout error message to stderr and exit 1. 12 13 # Description of argument(s): 14 # description A description of what was being expected 15 # (e.g. "an SOL login prompt"). 16 17 global spawn_id 18 global expect_out 19 20 set timeout [get_stack_var timeout {} 2] 21 22 if { $timeout == 1 } { 23 set seconds "second" 24 } else { 25 set seconds "seconds" 26 } 27 28 puts stderr "" 29 print_error "Did not get ${description} after $timeout ${seconds}.\n" 30 # Using uplevel to be able to access expect_out. 31 if { [ catch {uplevel { puts stderr [sprint_var expect_out]}} result ] } { 32 puts stderr [sprint_varx expect_out "<not set>"] 33 } 34 # If caller has exit_proc defined, call it. Otherwise, just call exit. 35 if { [info procs "exit_proc"] != "" } { 36 exit_proc 1 37 } 38 exit 1 39 40} 41 42 43proc handle_eof { description } { 44 45 # Print end-of-file error message to stderr and exit 1. 46 47 # Description of argument(s): 48 # description A description of what was being expected 49 # (e.g. "an SOL login prompt"). 50 51 global spawn_id 52 53 puts stderr "" 54 print_error "Reached end of file before getting $description.\n" 55 # Using uplevel to be able to access expect_out. 56 if { [ catch {uplevel { puts stderr [sprint_var expect_out]}} result ] } { 57 puts stderr [sprint_varx expect_out "<not set>"] 58 } 59 # If caller has exit_proc defined, call it. Otherwise, just call exit. 60 if { [info procs "exit_proc"] != "" } { 61 exit_proc 1 62 } 63 exit 1 64 65} 66 67 68proc expect_wrap {pattern_list message {timeout 15}} { 69 70 # Run the expect command for the caller and return the list index of the 71 # matching pattern. 72 73 # This function offers the following benefits over calling the expect 74 # command directly: 75 # - It makes program debug easier. When the program is run with --debug=1, 76 # this function prints useful debug output. 77 # - It will do standardized timeout and eof handling. 78 79 # Description of argument(s): 80 # pattern_list A list of patterns to be matched. If one 81 # of the patterns matches, the list index of 82 # the matching item will be returned. By 83 # default, each pattern is presumed to be a 84 # regex. If the caller wishes to, they may 85 # precede each pattern with either of the 86 # following: "-re ", "-gl " or "-ex " in 87 # order to explicitly choose the kind of 88 # match to be done.. 89 # message A message explaining what is being 90 # expected (e.g. "an SOL login prompt"). 91 # This will be included in output messages. 92 # timeout The expect timeout value. 93 94 # Example usage: 95 # set result [expect_wrap\ 96 # [list $bad_user_pw_regex "sh: xauth: command not found"]\ 97 # "an SOL prompt" 10] 98 # 99 # switch $result { 100 # 0 { 101 # puts stderr "" ; print_error "Invalid username or password.\n" 102 # exit_proc 1 103 # } 104 # 1 { 105 # dict set state ssh_logged_in 1 106 # } 107 # } 108 109 global spawn_id 110 global expect_out 111 112 # Recognized flags. 113 set flags [list "-re" "-ex" "-gl"] 114 115 # This helps debug efforts by removing leftover, stale entries. 116 array unset expect_out \[1-9\],string 117 118 # Prepare the expect statement. 119 append cmd_buf "global spawn_id\n" 120 append cmd_buf "global expect_out\n" 121 append cmd_buf "expect {\n" 122 set ix 0 123 foreach pattern $pattern_list { 124 # Check to see whether the caller has specified a flag (e.g. "-re", 125 # "-ex", etc.) at the beginning of the pattern. 126 set tokens [split $pattern " "] 127 if { [lsearch $flags [lindex $tokens 0]] != -1 } { 128 # Caller specified a flag. 129 set flag [lindex $tokens 0] 130 # Strip the flag from the pattern. 131 set pattern [string range $pattern 4 end] 132 } else { 133 set flag "-re" 134 } 135 append cmd_buf " ${flag} {$pattern} {set expect_result $ix}\n" 136 incr ix 137 } 138 append cmd_buf " timeout {handle_timeout \$message}\n" 139 append cmd_buf " eof {handle_eof \$message}\n" 140 append cmd_buf "}\n" 141 142 dprint_timen "Expecting $message." 143 dprint_issuing "\n${cmd_buf}" 144 eval ${cmd_buf} 145 146 dprintn ; dprint_vars expect_out expect_result 147 148 return $expect_result 149 150} 151 152 153proc send_wrap {buffer {add_lf 1}} { 154 155 # Send the buffer to the spawned process. 156 157 # This function offers the following benefits over calling the send command 158 # directly: 159 # - It makes program debug easier. When the program is run with --debug=1, 160 # this function prints useful debug output. 161 162 # Description of argument(s): 163 # buffer The string to be sent to the spawned 164 # process. 165 # add_lf Send a line feed after sending the buffer. 166 167 # Example usage. 168 # Close the ssh session. 169 # send_wrap "~." 170 # 171 # set expect_result [expect_wrap\ 172 # [list "Connection to $host closed"]\ 173 # "a connection closed message" 5] 174 175 global spawn_id 176 global expect_out 177 178 set cmd_buf "send -- {${buffer}}" 179 dprint_issuing 180 eval ${cmd_buf} 181 182 if { $add_lf } { 183 send -- "\n" 184 set cmd_buf "send -- \"\\n\"" 185 dprint_issuing 186 eval ${cmd_buf} 187 } 188 189} 190