# Kerberos rcp test.
# This is a DejaGnu test script.
# This script tests Kerberos rcp.
# Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.

# Find the programs we need.  We use the binaries from the build tree
# if they exist.  If they do not, then they must be in PATH.  We
# expect $objdir to be .../kerberos/src.

if ![info exists RCP] {
    set RCP [findfile $objdir/../../appl/bsd/rcp]
}

if ![info exists KRSHD] {
    set KRSHD [findfile $objdir/../../appl/bsd/kshd]
}

# Remove old wrapper script
    catch "exec rm -f $tmppwd/rcp"

# Make sure .k5login is reasonable.
if ![check_k5login rcp] {
    return
}

# Set up the kerberos database.
if {![get_hostname] \
    || ![setup_kerberos_files] \
    || ![setup_kerberos_env] \
    || ![setup_kerberos_db 0]} {
    return
}

# A procedure to start up the rsh daemon (rcp talks to the rsh
# daemon).

proc start_rsh_daemon { } {
    global REALMNAME
    global KRSHD
    global RCP
    global tmppwd
    global krshd_spawn_id
    global krshd_pid

    # Setup the shared library wrapper for login.krb5
    if ![file exists $tmppwd/rcp] {
	    setup_wrapper $tmppwd/rcp "$RCP $*"
    }


    # The -D argument tells it to accept a single connection, so we
    # don't need to use inetd.  The 3544 is the port to listen at.
    #
    # The -L ENV_SET is for the I/S Athena brokeness in dot files where
    #	LD_LIBRARY_PATH will be overridden causing the "exec csh -c rcp ..." 
    #	to fail as the .cshrc is read in. We do not use the -f option as
    #	a users shell might be sh...
    #	Later a proper fix would be to have kshd exec rcp directly
    #   shell indirection...
    spawn $KRSHD -k -c -D 3544 -P $tmppwd -S $tmppwd/srvtab -M $REALMNAME -L ENV_SET
    set krshd_spawn_id $spawn_id
    set krshd_pid [exp_pid]

    # Give the rsh daemon a few seconds to get set up.
    catch "exec sleep 2"
}

# A procedure to stop the rsh daemon.

proc stop_rsh_daemon { } {
    global krshd_spawn_id
    global krshd_pid

    if [info exists krshd_pid] {
	catch "exec kill $krshd_pid"
	catch "expect -i $krshd_spawn_id eof"
	catch "close -i $krshd_spawn_id"
	catch "wait -i $krshd_spawn_id"
	unset krshd_pid
    }
}

# Create a file to use for rcp testing.
set file [open $tmppwd/rcp-test w]
puts $file "This file is used for rcp testing."
close $file

# Test that a file was copied correctly.
proc check_file { filename } {
    if ![file exists $filename] {
	verbose "$filename does not exist"
	send_log "$filename does not exist\n"
	return 0
    }

    set file [open $filename r]
    if { [gets $file line] == -1 } {
	verbose "$filename is empty"
	send_log "$filename is empty\n"
	close $file
	return 0
    }

    if ![string match "This file is used for rcp testing." $line] {
	verbose "$filename contains $line"
	send_log "$filename contains $line\n"
	close $file
	return 0
    }

    if { [gets $file line] != -1} {
	verbose "$filename is too long ($line)"
	send_log "$filename is too long ($line)\n"
	close $file
	return 0
    }

    close $file

    return 1
}

# Test copying one file to another.
proc rcp_one_test { testname options frompref topref } {
    global REALMNAME
    global RCP
    global tmppwd

    send_log "rm -f $tmppwd/copy\n"
    verbose "exec rm -f $tmppwd/copy"
    catch "exec rm -f $tmppwd/copy"

    set from [format "%s%s" $frompref $tmppwd/rcp-test]
    set to [format "%s%s" $topref $tmppwd/copy]

    send_log "$RCP $options -D 3544 -N -k $REALMNAME $from $to\n"
    verbose "$RCP $options -D 3544 -N -k $REALMNAME $from $to"
    catch "exec $RCP $options -D 3544 -N -k $REALMNAME $from $to" exec_output

    if ![string match "" $exec_output] {
	send_log "$exec_output\n"
	verbose "$exec_output"
	fail $testname
	return 0
    }

    if ![check_file $tmppwd/copy] {
	fail $testname
	return 0
    }

    pass $testname

    return 1
}

# Wrap the tests in a procedure, so that we can kill the daemons if
# we get some sort of error.

proc rcp_test { } {
    global RCP
    global KEY
    global hostname
    global hostname
    global env

    # Start up the kerberos and kadmind daemons and get a srvtab and a
    # ticket file.
    if {![start_kerberos_daemons 0] \
        || ![add_kerberos_key host/$hostname 0] \
        || ![setup_srvtab 0] \
	|| ![add_kerberos_key $env(USER) 0] \
	|| ![kinit $env(USER) $env(USER)$KEY 0]} {
	return
    }

    rcp_one_test "local rcp" "" "" ""

    start_rsh_daemon
    rcp_one_test "rcp from" "" "$hostname:" ""
    stop_rsh_daemon

    start_rsh_daemon
    rcp_one_test "rcp to" "" "" "$hostname:"
    stop_rsh_daemon

    # Doing rcp between two hosts actually just executes rsh rcp on
    # the source.  We could test this, but we're not set up for it
    # right now.  Also, it's pretty much covered by the other rcp
    # tests and by the rsh tests.
    # start_rsh_daemon
    # rcp_one_test "rcp between" "" "$hostname:" "$hostname:"
    # stop_rsh_daemon

    start_rsh_daemon
    rcp_one_test "encrypted rcp from" "-x -c $env(KRB5CCNAME) -C $env(KRB5_CONFIG)" "$hostname:" ""
    stop_rsh_daemon

    start_rsh_daemon
    rcp_one_test "encrypted rcp to" "-x -c $env(KRB5CCNAME) -C $env(KRB5_CONFIG)" "" "$hostname:"
    stop_rsh_daemon

    # Doing rcp between two hosts actually just executes rsh rcp on
    # the source.  We could test this, but we're not set up for it
    # right now.  Also, it's pretty much covered by the other rcp
    # tests and by the rsh tests.
    # start_rsh_daemon
    # rcp_one_test "encrypted rcp between" "-x" "$hostname:" "$hostname:"
    # stop_rsh_daemon
}

# Run the test.
set status [catch rcp_test msg]

# Shut down the kerberos daemons and the rsh daemon.
stop_kerberos_daemons

stop_rsh_daemon

if { $status != 0 } {
    send_error "ERROR: error in rcp.exp\n"
    send_error "$msg\n"
    exit 1
}
