genx1mx6
genx1mx6

Reputation: 443

TCL / Expect - After Interact, expect_user doesn't echo

So I have a simple script that logs into a network device, and then interacts allowing users to call various macros. I have an example below- the user is in the device, hits "!p" and then the script wants the user to input a command.

all works fine, except the program isn't echoing what the user types so it's impossible for them to correct mistypes.

The solution I have currently is stty echo before expect_user and stty -echo after. But in this solution, backspaces and arrow key presses are captured so the user still cannot correct their mistype.

I'm not exactly sure how to fix this, but what I assume is happening is the spawned program has control of STDOUT so when expect_user is called, it's in the background.

set hostname 10.0.0.1
set password 1234qwer

spawn ssh -o StrictHostKeyChecking=no $hostname
expect {
        "assword:" {
                        send "$password\r"
                        expect "#"
        }
}
interact {
        "!p" {
                send_user "\nInput command: "
                expect_user -re "(.*)\r" {
                        puts "\n$expect_out(1,string)"
                }
        }
}

Upvotes: 1

Views: 1493

Answers (1)

Dinesh
Dinesh

Reputation: 16428

In its simplest form, the interact command sets up a connection between the user and the currently spawned process. The user's terminal is put into raw mode so that the connection is transparent.

Raw mode is a specific type of character-oriented mode, where no special interpretations are applied to input characters. For instance, Ctrl-C no longer serves as an interrupt, and Ctrl-D no longer acts as an eof. The opposite of raw mode is cooked mode. It represents the most common form of line-oriented modes.

So, to achieve what you want, you have to put the terminal into cooked mode before prompting for the input from the user.

stty -raw echo; # Put the terminal to cooked mode, echo is enabled.
stty raw -echo; # Put the terminal to raw mode, echo is disabled.

Since the terminal is in raw mode for interact, it won't echo the characters at all, which you might have already noticed. i.e. when you type !p, you won't see that at all. There is an option available to make it echoed. -echo flag with interact will do that job.

For example, interact -echo "Hello" {puts " World"} will echo Hello , while user typing it. This can be added as well to your script.

Adding all these aspects, the finalized code can be written as follows,

interact {
         -echo "!p" {
                send_user "\nInput command: "
                stty -raw echo; # Enabling cooked mode
                expect_user -re "(.*)\n" {
                        set input $expect_out(1,string)
                        puts "You have typed : $input"
                        # Process the user input as per your idea
                }
                stty raw -echo; # Enabling raw mode again.
          }
}

Upvotes: 2

Related Questions