blob: 7d0f8f2093ce285919b776a3b2d7e16dba7e204f [file] [log] [blame]
Michael Walshaa245bb2018-02-20 11:30:00 -06001#!/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
Michael Walsha0a42402018-02-27 10:50:40 -060017 global spawn_id
18 global expect_out
19
Michael Walshaa245bb2018-02-20 11:30:00 -060020 set timeout [get_stack_var timeout {} 2]
21
22 if { $timeout == 1 } {
23 set seconds "second"
24 } else {
25 set seconds "seconds"
26 }
Michael Walsha0a42402018-02-27 10:50:40 -060027
Michael Walshaa245bb2018-02-20 11:30:00 -060028 puts stderr ""
29 print_error "Did not get ${description} after $timeout ${seconds}.\n"
Michael Walsha0a42402018-02-27 10:50:40 -060030 # 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 }
Michael Walshaa245bb2018-02-20 11:30:00 -060034 # 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
Michael Walsha0a42402018-02-27 10:50:40 -060051 global spawn_id
52
Michael Walshaa245bb2018-02-20 11:30:00 -060053 puts stderr ""
54 print_error "Reached end of file before getting $description.\n"
Michael Walsha0a42402018-02-27 10:50:40 -060055 # 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 }
Michael Walshaa245bb2018-02-20 11:30:00 -060059 # 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}
Michael Walsha0a42402018-02-27 10:50:40 -060066
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}