Work around bug in AIX 7.1 awk in report card tool
[dejagnu.git] / lib / ssh.exp
blob5c2fbe01c66097e49b2647c57afabbf5e0600f12
1 # Copyright (C) 2016-2019, 2020 Free Software Foundation, Inc.
3 # This file is part of DejaGnu.
5 # DejaGnu is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # DejaGnu is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with DejaGnu.  If not, see <http://www.gnu.org/licenses/>.
18 # Connect using ssh(1).
20 set ssh_initialized "no"
21 set ssh_useropts " -o ControlPersist=yes -o ControlMaster=auto -o ControlPath=\"/tmp/ssh-%r@%h:%p\""
23 # Default to the ssh and scp in the user's path.
24 set SSH ssh
25 set SCP scp
27 # Download SRCFILE to DESTFILE on DESTHOST.
29 proc ssh_download {desthost srcfile destfile} {
30     global SSH SCP ssh_initialized timeout
32     set ssh_port ""
33     set ssh_user ""
34     set ssh_useropts ""
35     set name ""
36     set hostname ""
38     if {[board_info $desthost exists scp_prog]} {
39         set SCP [board_info $desthost scp_prog]
40     }
42     if {[board_info $desthost exists ssh_prog]} {
43         set SSH [board_info $desthost ssh_prog]
44     }
46     # The default user name is the person running the tests
47     if {[board_info $desthost exists username]} {
48         set ssh_user "[board_info $desthost username]@"
49     }
51     if {[board_info $desthost exists ssh_opts]} {
52         append ssh_useropts " [board_info $desthost ssh_opts]"
53     }
55     # The default SSH port is 22
56     if {[board_info $desthost exists port]} {
57         set ssh_port "[board_info $desthost port]"
58     } else {
59         set ssh_port 22
60     }
62     if {[board_info $desthost exists name]} {
63         set name [board_info $desthost name]
64     }
66     if {[board_info $desthost exists hostname]} {
67         set hostname [board_info $desthost hostname]
68     } else {
69         set hostname $desthost
70     }
72     append ssh_useropts " -o ControlPersist=yes -o ControlMaster=auto -o ControlPath=/tmp/ssh-%r@%h:%p"
74     set ret [local_exec "$SCP -P $ssh_port $ssh_useropts $srcfile $ssh_user$hostname:$destfile" "" "" $timeout]
75     set status [lindex $ret 0]
76     set output [lindex $ret 1]
77     if { $status == 0 } {
78         set ssh_initialized "yes"
79         verbose "Copied $srcfile to $desthost:$destfile" 2
80         return $destfile
81     } else {
82         verbose "Download via ssh to $desthost failed."
83         return ""
84     }
87 proc ssh_upload {desthost srcfile destfile} {
88     global SSH SCP
90     if {[board_info $desthost exists scp_prog]} {
91         set SCP [board_info $desthost scp_prog]
92     }
94     if {[board_info $desthost exists username]} {
95         set ssh_user "[board_info $desthost username]@"
96     } else {
97         set ssh_user ""
98     }
100     if {[board_info $desthost exists name]} {
101         set desthost [board_info $desthost name]
102     }
104     if {[board_info $desthost exists hostname]} {
105         set desthost [board_info $desthost hostname]
106     }
108     set status [catch "exec $SCP $ssh_user$desthost:$srcfile $destfile" output]
109     if { $status == 0 } {
110         verbose "Copied $desthost:$srcfile to $destfile" 2
111         return $destfile
112     } else {
113         verbose "Upload from $desthost failed, $output."
114         return ""
115     }
118 # Execute CMD on BOARDNAME.
120 proc ssh_exec { boardname program pargs inp outp } {
121     global SSH timeout
123     set ssh_port ""
124     set scp_port ""
125     set ssh_user ""
126     set ssh_useropts ""
127     set name ""
128     set hostname ""
130     verbose "Executing on $boardname: $program $pargs"
132     if {![board_info $boardname exists ssh_prog]} {
133         set SSH ssh
134     } else {
135         set SSH [board_info $boardname ssh_prog]
136     }
138     if {[board_info $boardname exists username]} {
139         set ssh_user "[board_info $boardname username]@"
140     } else {
141         set ssh_user ""
142     }
144     if {[board_info $boardname exists ssh_useropts]} {
145         append ssh_useropts " [board_info $boardname ssh_opts]"
146     }
148     if {[board_info $boardname exists name]} {
149         set boardname [board_info $boardname name]
150     }
152     if {[board_info $boardname exists hostname]} {
153         set hostname [board_info $boardname hostname]
154     } else {
155         set hostname $boardname
156     }
158     if {[board_info $boardname  exists port]} {
159         append ssh_useropts " -p [board_info $boardname port]"
160     }
162     append ssh_useropts " -o ControlPersist=yes -o ControlMaster=auto -o ControlPath=\"/tmp/ssh-%r@%h:%p\""
164     # If CMD sends any output to stderr, exec will think it failed.
165     # More often than not that will be true, but it doesn't catch the
166     # case where there is no output but the exit code is non-zero.
167     if { $inp eq "" } {
168         set inp "/dev/null"
169     }
171     # We use && here, as otherwise the echo always works, which makes it look
172     # like execution succeeded when in reality it failed.
173     set ret [local_exec "$SSH $ssh_useropts $ssh_user$hostname sh -c '$program $pargs 2>&1 && echo XYZ\\\${?}ZYX \\; rm -f $program'" $inp $outp $timeout]
174     set status [lindex $ret 0]
175     set output [lindex $ret 1]
177     verbose "$SSH status is $status, output is $output"
179     # `status' doesn't mean much here other than ssh worked ok.
180     # What we want is whether $program ran ok.  Return $status
181     # if the program timed out, status will be 1 indicating that
182     # ssh ran and failed.  If ssh fails, we will get FAIL rather
183     # than UNRESOLVED - this will help the problem be noticed.
184     if { $status != 0 } {
185         regsub "XYZ(\[0-9\]*)ZYX\n?" $output "" output
186         return [list $status "$SSH to $boardname failed for $program, $output"]
187     }
188     if { [regexp "XYZ(\[0-9\]*)ZYX" $output junk status] == 0 } {
189         set status ""
190     }
191     verbose "ssh_exec: status:$status text:$output" 4
192     if { $status eq "" } {
193         return [list -1 "Couldn't parse $SSH output, $output."]
194     }
195     regsub "XYZ(\[0-9\]*)ZYX\n?" $output "" output
196     return [list [expr {$status != 0}] $output]
199 proc ssh_close { desthost } {
200     global SSH ssh_initialized
202     verbose "Closing the SSH connection to $desthost"
204     set ssh_port ""
205     set scp_port ""
206     set ssh_user ""
207     set ssh_useropts ""
208     set name ""
209     set hostname ""
211     if {[board_info $desthost exists username]} {
212         set ssh_useropts "-l [board_info $desthost username]"
213         set ssh_user "[board_info $desthost username]@"
214     } else {
215         set ssh_user ""
216         set ssh_useropts ""
217     }
219     if {[board_info $desthost exists hostname]} {
220         set hostname [board_info $desthost hostname]
221     }
223     if {[board_info $desthost exists ssh_opts]} {
224         append ssh_useropts " [board_info $desthost ssh_opts]"
225     }
227     if {[board_info $desthost exists port]} {
228         set ssh_port " -p [board_info $desthost port]"
229     } else {
230         set ssh_port ""
231     }
233     set args "$ssh_user$hostname $ssh_port"
235    # Kill the remote server
236     set status [catch "exec ssh $ssh_port -o ControlPath=/tmp/ssh-%r@%h:%p -O exit $args"]
237     set ssh_initialized "no"
239      return ""