| # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software |
| # Foundation, Inc. |
| # |
| # This file is part of DejaGnu. |
| # |
| # DejaGnu is free software; you can redistribute it and/or modify it |
| # under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2 of the License, or |
| # (at your option) any later version. |
| # |
| # DejaGnu 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 GNU |
| # General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with DejaGnu; if not, write to the Free Software Foundation, |
| # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| |
| # This file was written by Bob Manson (manson@cygnus.com) |
| |
| # |
| # Open a connection to the remote DOS host. |
| # |
| proc dos_open { dest args } { |
| global destbat_num |
| |
| if ![info exists destbat_num] { |
| set destbat_num [pid] |
| } |
| if { [board_info $dest conninfo] == "" } { |
| global board_info |
| set name [board_info $dest name] |
| |
| set board_info($name,conninfo) "b${destbat_num}.bat" |
| incr destbat_num |
| } |
| |
| if [board_info $dest exists fileid] { |
| return [board_info $dest fileid] |
| } |
| |
| verbose "doing a dos_open to $dest" |
| |
| set shell_prompt [board_info $dest shell_prompt] |
| |
| set shell_id [remote_raw_open $dest] |
| |
| if { $shell_id == "" || $shell_id < 0 } { |
| return -1 |
| } |
| |
| if [board_info $dest exists init_command] { |
| remote_send $dest "[board_info $dest init_command]\n" |
| remote_expect $dest 10 { |
| -re "$shell_prompt" { } |
| default { |
| perror "failed connection to DOS on $dest." |
| return -1 |
| } |
| } |
| } |
| |
| if [board_info $dest exists ftp_directory] { |
| set dir [board_info $dest ftp_directory] |
| regsub -all "/" "$dir" "\\" dir |
| remote_send $dest "cd $dir\n" |
| remote_expect $dest 10 { |
| -re "$shell_prompt" { } |
| default { |
| perror "failed connection to DOS on $dest." |
| return -1 |
| } |
| } |
| } |
| |
| if [board_info $dest exists dos_dir] { |
| set dos_dir [board_info $dest dos_dir] |
| regsub -all "^(\[a-zA-Z]:).*$" "$dos_dir" "\\1" drive |
| regsub -all "^\[a-zA-Z]:" "$dos_dir" "" dos_dir |
| remote_send $dest "${drive}\n" |
| remote_expect $dest 10 { |
| -re "$shell_prompt" { } |
| default { |
| perror "failed connection to DOS on $dest." |
| return -1 |
| } |
| } |
| remote_send $dest "cd $dos_dir\n" |
| remote_expect $dest 10 { |
| -re "$shell_prompt" { } |
| default { |
| perror "failed connection to DOS on $dest." |
| return -1 |
| } |
| } |
| } |
| |
| global target_alias |
| if [info exists target_alias] { |
| set talias $target_alias |
| } else { |
| set talias "foo-bar" |
| } |
| |
| global board_info |
| if [board_info $dest exists name] { |
| set n [board_info $dest name] |
| } else { |
| set n $dest |
| } |
| set board_info($n,fileid) $shell_id |
| |
| if [board_info $dest exists init_script] { |
| remote_exec $dest "[board_info $dest init_script] $talias" |
| } |
| |
| verbose "Succeeded in connecting to DOS." |
| return $shell_id |
| } |
| |
| # |
| # Close the connection to the remote host. If we're telnetting there, we |
| # need to exit the connection first (ataman telnetd gets confused otherwise). |
| # |
| proc dos_close { dest args } { |
| if [board_info $dest exists fileid] { |
| if { [board_info $dest connect] == "telnet" } { |
| remote_send $dest "exit\n" |
| sleep 2 |
| } |
| return [remote_raw_close $dest] |
| } |
| } |
| |
| proc dos_prep_command { dest cmdline } { |
| global board_info |
| |
| set name [board_info $dest name] |
| set shell_id [remote_open "$dest"] |
| |
| set localbat "/tmp/b[pid].bat" |
| set remotebat [board_info $dest conninfo] |
| |
| verbose "opened" |
| if { $shell_id != "" && $shell_id >= 0 } { |
| set fileid [open "$localbat" "w"] |
| puts -nonewline $fileid "@echo off\r\n$cmdline\r\nif errorlevel 1 echo *** DOSEXIT code 1\r\nif not errorlevel 1 echo *** DOSEXIT code 0\r\n" |
| close $fileid |
| set result [remote_download $dest $localbat $remotebat] |
| } else { |
| set result "" |
| } |
| remote_file build delete $localbat |
| return $result |
| } |
| |
| # |
| # Run CMDLINE on DESTHOST. We handle two cases; one is where we're at |
| # a DOS prompt, and the other is where we're in GDB. |
| # We run CMDLINE by creating a batchfile, downloading it, and then |
| # executing it; this handles the case where the commandline is too |
| # long for command.com to deal with. |
| # |
| |
| proc dos_exec { dest program pargs inp outp } { |
| set cmdline "$program $pargs" |
| |
| set shell_prompt [board_info $dest shell_prompt] |
| |
| if { $inp != "" } { |
| set inp [remote_download $dest $inp inpfile] |
| if { $inp != "" } { |
| set inp " < $inp" |
| } |
| } |
| |
| if { $outp != "" } { |
| set outpf " > tempout" |
| } else { |
| set outpf "" |
| } |
| |
| verbose "cmdline is $cmdline$inp." 2 |
| |
| # Make a DOS batch file; we use @echo off so we don't have to see |
| # the DOS command prompts and such. |
| for { set i 0 } { $i < 2 } { incr i } { |
| set exit_status -1 |
| verbose "calling open" |
| set batfile [dos_prep_command $dest "$cmdline$inp$outpf"] |
| if { $batfile != "" } { |
| if { [dos_start_command $batfile $dest] == "" } { |
| # FIXME: The 300 below should be a parameter. |
| set result [remote_wait $dest 300] |
| set exit_status [lindex $result 0] |
| set output [lindex $result 1] |
| } |
| } |
| if { $exit_status >= 0 } { |
| if { $outp != "" } { |
| remote_upload $dest tempout $outp |
| remote_file $dest delete tempout |
| } |
| return [list $exit_status $output] |
| } |
| if { $exit_status != -2 } { |
| remote_close $dest |
| remote_reboot $dest |
| } |
| } |
| return [list -1 "program execution failed"] |
| } |
| |
| # |
| # Start CMDLINE executing on DEST. |
| # There are two cases that we handle, one where we're at a DOS prompt |
| # and the other is when the remote machine is running GDB. |
| # |
| |
| proc dos_start_command { cmdline dest } { |
| set shell_prompt [board_info $dest shell_prompt] |
| set prefix "" |
| set ok 0 |
| for { set i 0 } {$i <= 2 && ! $ok} { incr i } { |
| set shell_id [remote_open $dest] |
| if { $shell_id != "" && $shell_id > 0 } { |
| remote_send $dest "echo k\r" |
| remote_expect $dest 20 { |
| -re "\\(gdb\\)" { |
| set shell_prompt "\\(gdb\\)" |
| # gdb uses 'shell command'. |
| set prefix "shell " |
| set ok 1 |
| } |
| -re "$shell_prompt" { |
| set ok 1 |
| } |
| default { } |
| } |
| } |
| if { ! $ok } { |
| remote_close $dest |
| remote_reboot $dest |
| } |
| } |
| if { ! $ok } { |
| return "unable to start command" |
| } else { |
| remote_send $dest "${prefix}${cmdline}\n" |
| remote_expect $dest 2 { |
| -re "${cmdline}\[\r\n\]\[\r\n\]?" { } |
| timeout { } |
| } |
| return "" |
| } |
| } |
| |
| # |
| # Send STRING to DEST, translating all LFs to CRs first, and sending one |
| # line at a time because of strangeness with telnet in some circumstances. |
| # |
| |
| proc dos_send { dest string } { |
| verbose "Sending '$string' to $dest" 2 |
| # Convert LFs to CRs, 'cause that is what DOS wants to see. |
| set first 1 |
| set string [string trimright $string "\r\n"] |
| foreach line [split $string "\r\n"] { |
| if {$first} { |
| set first 0 |
| } else { |
| # small delay between lines, to keep from |
| # overwhelming the stupid telnet server. |
| sleep 1.0 |
| } |
| remote_raw_send $dest "$line\r" |
| } |
| } |
| |
| # |
| # Spawn PROGRAM on DEST, and return the spawn_id associated with the |
| # connection; we can only spawn one command at a time. |
| # |
| |
| proc dos_spawn { dest program args } { |
| verbose "running $program on $dest" |
| set remotebat [dos_prep_command $dest $program] |
| |
| for { set x 0 } { $x < 3 } { incr x } { |
| if { [dos_start_command $remotebat $dest] == "" } { |
| return [board_info $dest fileid] |
| } |
| remote_close $dest |
| remote_reboot $dest |
| } |
| return -1 |
| } |
| |
| proc dos_wait { dest timeout } { |
| set output "" |
| set shell_prompt [board_info $dest shell_prompt] |
| set status 1 |
| |
| verbose "waiting in dos_wait" |
| remote_expect $dest $timeout { |
| -re "(.*)\[*\]\[*\]\[*\] DOSEXIT code (\[0-9\]+)\[\r\n\]\[\r\n\]?" { |
| verbose "got exit status" |
| append output $expect_out(1,string) |
| set status $expect_out(2,string) |
| exp_continue |
| } |
| |
| -re "(.*)${shell_prompt}" { |
| append output $expect_out(1,string) |
| verbose "output from dos is:'$output'" |
| return [list $status $output] |
| } |
| |
| -re "(.*)\\(gdb\\)" { |
| append output $expect_out(1,string) |
| return [list $status $output] |
| } |
| |
| -re "In.*cygwin.*except" { |
| remote_close $dest |
| remote_reboot $dest |
| return [list -2 $output] |
| } |
| |
| -re "\[\r\n\]+" { |
| # This is a bit obscure. We only want to put whole |
| # lines into the output string, because otherwise we |
| # might miss a prompt because we only got 1/2 of it the |
| # first time 'round. The other tricky bit is that |
| # expect_out(buffer) will contain everything before and including |
| # the matched pattern. |
| append output $expect_out(buffer) |
| exp_continue -continue_timer |
| } |
| |
| timeout { |
| warning "timeout in dos_wait" |
| if { [dos_interrupt_job $dest] == "" } { |
| return [list 1 $output] |
| } |
| } |
| |
| eof { |
| warning "got EOF from dos host." |
| } |
| } |
| |
| remote_close $dest |
| |
| return [list -1 $output] |
| } |
| |
| proc dos_load { dest prog args } { |
| global dos_dll_loaded |
| set progargs "" |
| set inpfile "" |
| if { [llength $args] > 0 } { |
| set progargs [lindex $args 1] |
| } |
| if { [llength $args] > 1 } { |
| set inpfile [lindex $args 1] |
| } |
| if ![info exists dos_dll_loaded] { |
| if ![is_remote host] { |
| global target_alias |
| |
| set comp [get_multilibs] |
| if [file exists "${comp}/winsup/new-cygwin1.dll"] { |
| set dll "${comp}/winsup/new-cygwin1.dll" |
| set dll_name "cygwin1.dll" |
| } elseif [file exists "${comp}/winsup/new-cygwin.dll"] { |
| set dll "${comp}/winsup/new-cygwin.dll" |
| set dll_name "cygwin.dll" |
| } elseif [file exists ${comp}/lib/cygwin1.dll] { |
| set dll "${comp}/lib/cygwin1.dll" |
| set dll_name "cygwin1.dll" |
| } elseif [file exists ${comp}/lib/cygwin.dll] { |
| set dll "${comp}/lib/cygwin.dll" |
| set dll_name "cygwin.dll" |
| } else { |
| error "couldn't find cygwin.dll:$comp" |
| return "fail" |
| } |
| remote_download $dest $dll $dll_name |
| } |
| set dos_dll_loaded 1 |
| } |
| set remote_prog [remote_download $dest $prog "aout.exe"] |
| set result [remote_exec $dest $remote_prog $progargs $inpfile] |
| set status [lindex $result 0] |
| set output [lindex $result 1] |
| set status2 [check_for_board_status output] |
| if { $status2 >= 0 } { |
| set status $status2 |
| } |
| if { $status != 0 } { |
| set status "fail" |
| } else { |
| set status "pass" |
| } |
| return [list $status $output] |
| } |
| |
| proc dos_file { dest op args } { |
| switch $op { |
| delete { |
| foreach x $args { |
| remote_exec $dest "del" "$x" |
| } |
| return |
| |
| } |
| default { |
| return [eval standard_file \{$dest\} \{$op\} $args] |
| } |
| } |
| } |
| |
| # |
| # Interrupt the current spawned command being run; the only tricky |
| # part is that we have to handle the "Terminate batch job" prompt. |
| # |
| proc dos_interrupt_job { host } { |
| set shell_prompt [board_info $host shell_prompt] |
| |
| remote_send $host "\003" |
| remote_expect $host 10 { |
| -re "Terminate batch job.*Y/N\[)\]\[?\] *$" { |
| remote_send $host "n\n" |
| exp_continue |
| } |
| -re "$shell_prompt" { |
| return "" |
| } |
| -re ">" { |
| remote_send $host "\n" |
| exp_continue |
| } |
| } |
| return "fail" |
| } |
| |
| proc dos_copy_download { host localfile remotefile } { |
| remote_file build delete "[board_info $host local_dir]/$remotefile" |
| if [remote_file build exists $localfile] { |
| set result [remote_download build $localfile "[board_info $host local_dir]/$remotefile"] |
| if { $result != "" } { |
| remote_exec build "chmod" "a+rw $result" |
| return $remotefile |
| } |
| } else { |
| return "" |
| } |
| } |
| |
| proc dos_copy_upload { host remotefile localfile } { |
| remote_file build delete $localfile |
| if [file exists "[board_info $host local_dir]/$remotefile"] { |
| set result [remote_download build "[board_info $host local_dir]/$remotefile" $localfile] |
| } else { |
| set result "" |
| } |
| if { $result != "" } { |
| remote_exec build "chmod" "a+rw $result" |
| return $result |
| } |
| } |
| |
| proc dos_copy_file { dest op args } { |
| if { $op == "delete" } { |
| set file "[board_info $dest local_dir]/[lindex $args 0]" |
| remote_file build delete $file |
| } |
| } |
| |
| set_board_info protocol "dos" |
| set_board_info shell_prompt "(^|\[\r\n\])\[a-zA-Z\]:\[^\r\n\]*>\[ \t\]*$" |
| set_board_info needs_status_wrapper 1 |