# Copyright (C) 1992 - 2002 Free Software Foundation, Inc.

# This program 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.
# 
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  

# Please email any bugs, comments, and/or additions to this file to:
# bug-dejagnu@gnu.org

#
# Support downloading files using ftp.
#

#
# Open a connection to HOST.
#
proc ftp_open { host } {
    set prompt "ftp>"
    global board_info

    if [board_info $host exists name] {
	set host [board_info $host name];
    }

    if [board_info $host exists ftp_fileid] {
	return [board_info $host ftp_fileid];
    }

    if [board_info $host exists hostname] {
	set remotehost [board_info $host hostname];
    } else {
	set remotehost $host;
    }

    # LoseQVT tends to get stuck sometimes; we'll loop around a few million
    # times when it gets a "connection refused".
    set spawn_id -1;
    set count 3;
    while { $spawn_id < 0 && $count >= 0 } {
	spawn ftp -n $remotehost;
	expect {
	    -i $spawn_id -re ".*220.*$prompt" { }
	    -i $spawn_id -re ".*Connection refused.*$prompt" {
		sleep 2;
		send "open $remotehost\n";
		exp_continue
	    }
	    -i $spawn_id default {
		close -i $spawn_id;
		wait -i $spawn_id;
		set spawn_id -1;
	    }
	}
	incr count -1;
    }
    if { $spawn_id < 0 } {
	return -1;
    }
    set board_info($host,ftp_fileid) $spawn_id;
    if [board_info $host exists ftp_username] {
	if [board_info $host exists ftp_password] {
	    set command "user [board_info $host ftp_username] [board_info $host ftp_password]\n";
	} else {
	    set command "user [board_info $host ftp_username]\n";
	}
	send "$command"
	expect {
	    -i $spawn_id -re ".*230.*$prompt" { }
	    -i $spawn_id default {
		close -i $spawn_id;
		wait -i $spawn_id;
		return -1;
	    }
	}
    }
    set timeout 15
    send -i $spawn_id "binary\n"
    expect {
	-i $spawn_id -re "200.*$prompt" { }
	-i $spawn_id timeout {
	    close -i $spawn_id;
	    wait -i $spawn_id;
	    return -1
	}
    }
    if [board_info $host exists ftp_directory] {
	send "cd [board_info $host ftp_directory]\n";
	expect {
	    -i $spawn_id -re "250.*$prompt" { }
	    -i $spawn_id default {
		close -i $spawn_id;
		wait -i $spawn_id;
		return -1;
	    }
	}
    }

    if [board_info $host exists ftp_no_passive] {
	send "passive\n";
	expect {
	    -i $spawn_id -re "Passive mode off.*$prompt" { }
	    -i $spawn_id -re "Passive mode on.*$prompt" {
		send "passive\n";
		exp_continue;
	    }
	    -i $spawn_id -re ".*$prompt" { }
	}
    }

    set board_info($host,ftp_fileid) $spawn_id;
    return $spawn_id;
}

#
# Grab REMOTEFILE from HOST and store it as LOCALFILE.
#
proc ftp_upload { host remotefile localfile } {
    set prompt "ftp>"

    verbose "ftping $remotefile from $host to $localfile"
    set timeout 15
    set spawn_id [ftp_open $host];
    if { $spawn_id < 0 } {
	return "";
    }
    set loop 1;

    while { $loop } {
	send -i $spawn_id "get $remotefile $localfile\n";
	expect {
	    -i $spawn_id -re ".*Too many open files.*$prompt" {
		ftp_close $host;
	    }
	    -i $spawn_id -re ".*No such file or directory.*$prompt" {
		set loop 0;
		set remotefile "";
	    }
	    -i $spawn_id -re "(^|\[\r\n\])226.*$prompt" { set loop 0; }
	    -i $spawn_id -re "(^|\[\r\n\])\[0-9\]\[0-9\]\[0-9\].*$prompt" {
		set loop 0;
		set remotefile ""; 
	    }
	    -i $spawn_id default {
		ftp_close $host;
	    }
	}
	if { $loop } {
	    set spawn_id [ftp_open $host];
	    if { $spawn_id < 0 } {
		return "";
	    }
	}
    }
    return $localfile;
}

#
# Download LOCALFILE to HOST as REMOTEFILE.
#
proc ftp_download { host localfile remotefile } {
    set prompt "ftp>"

    verbose "putting $localfile $remotefile"

    if [board_info $host exists hostname] {
	set remotehost [board_info $host hostname];
    } else {
	set remotehost $host;
    }
    
    set spawn_id [ftp_open $host];
    if { $spawn_id < 0 } {
	return "";
    }
    set loop 1;

    while { $loop } {
	send -i $spawn_id "put $localfile $remotefile\n"
	expect {
	    -i $spawn_id -re ".*Too many open files.*$prompt" {
		ftp_close $host;
	    }
	    -i $spawn_id -re ".*No such file or directory.*$prompt" {
		set loop 0;
		set remotefile "";
	    }
	    -re "(^|\[\r\n\])150.*connection for (.*) \[(\]\[0-9.,\]+\\)\[\r\n\]" {
		set remotefile $expect_out(2,string);
		exp_continue;
	    }
	    -i $spawn_id -re "(^|\[\r\n\])226.*$prompt" {
		set loop 0;
	    }
	    -i $spawn_id -re "Timeout.*$prompt" {
		ftp_close $host;
	    }
	    -i $spawn_id -re "(^|\[\r\n\])\[0-9\]\[0-9\]\[0-9\].*$prompt" {
		set loop 0; 
		set remotefile ""; 
	    }
	    -i $spawn_id default {
		ftp_close $host;
	    }
	}
	if { $loop } {
	    set spawn_id [ftp_open $host];
	    if { $spawn_id < 0 } {
		return "";
	    }
	}
    }
    return $remotefile;
}

#
# Close the connection.
#
proc ftp_close { host } {
    global board_info

    if [board_info $host exists name] {
	set host [board_info $host name];
    }

    if ![board_info $host exists ftp_fileid] {
	return "";
    }

    set spawn_id [board_info $host ftp_fileid];
    unset board_info($host,ftp_fileid);

    send -i $spawn_id "quit\n"
    close -i $spawn_id
    wait -i $spawn_id;
    return "";
}
