views:

209

answers:

3

I'm auto-interacting with an SSH session and an ERP program using Expect.

Rather than relying on a regular expression to capture a variable in my expect script would it be possible upon receiving a certain keystroke from a user to capture a screen region, say one field, into a variable in the code? Send the server some other commands and resend the field?

Say an order number is contained at 6, 12, 6, 18 (where 6 is the row and 12-18 are the columns) containing my 6 digit order number. I want to get that order number from row 6 columns 12 to 18 copy that into a variable. Then allow the user to interact some more (or expect a move into another menu), then re-send the order number in another menu.

So I guess my question is: Are the current screen's contents in one buffer? (not the whole session) Can you extract just a certain data element that would only exist at that row and column range on the screen?

Sample pseudocode:

#!/usr/bin/expect -f
set env(TERM) vt100
spawn ssh -Y user@domain
#... set user/pass and other vars...
#... send commands to log into ERP
#don't time out
set timeout -1 
        interact {
                -reset $CTRLZ {exec kill -STOP [pid]}
                $CTRLA   {   
                        exp_send "menu_address\ry\r"
                }
                $CTRLO   {   
                        #...acquire order number variable...
                        #...some code I don't understand yet...

                        exp_send "menu_exit_sequence\r"
                        exp_send "menu_address\r"
                        exp_send $ordernumvar

                }
                ~~
        }
A: 

No, you can't grab something off of the screen at a particular row/column. However, think about how the information got to the screen in the first place. If it's a tty-based application using curses it was output to stdout with special escape sequences that caused it to appear at that row/column. So, 'expect' those specific escape sequences to get what is at that position.

Bryan Oakley
What would be an example of one of these special escape sequences? I am somewhat unfamiliar with how tty-based applications display properly. Also how can I 'expect' my field if it's already on the screen and only after that does the user trigger their action to copy the variable? I guess it would not be impossible to predetermine the useful data elements for that menu and pre-load them into variables for possible use later.
jjclarkson
<esc>[1;3H would move the cursor to row 1, column 3, for example. I'm not sure how it can already be on your screen prior to running your expect script. Doesn't your script have to log in or start the other program in order for the initial screen to be displayed?
Bryan Oakley
Interesting... For the scenario I'm working on the script spawns an SSH session (the ERP program is started automatically upon login according to shell settings, though there is a login sequence also being automated by the script) then hands control to the user using 'interact' however certain keystrokes such as a Ctrl+o (and many others) would trigger some automated procedure then hand control back to the user. Cursor control is not necessary, only the selection of certain fields and the sending of certain commands.
jjclarkson
I've done some client side automation scripts (using a different method, namely screen-scraping) and in all of them I've relied on the ERP program to determine cursor position. I realize the Expect perspective is different, I'm trying to 'get' it :)
jjclarkson
The suggestion I was making is this: when you log in via expect, whatever normally goes to the screen presumably goes through expect. In that stream of data that is setting up the screen might be something that looks like "<esc>[1;3HYouDataHere". It's a longshot, but the point is, you are able to see all the data that goes to the screen, you just have to parse it.
Bryan Oakley
Now I'm totally with you. Is there a way to get a sane viewable output of those characters since they're created on the server (maybe a dump of a session in Expect?) so I can recreate them in the script? Or is that in the reference for VT100? like these: http://www.mit.edu/~vona/VonaUtils/vona/terminal/VT100_Escape_Codes.html
jjclarkson
I'm still looking for the right regex (http://stackoverflow.com/questions/2007321/regular-expression-to-find-string-in-expect-buffer) but you led me in the right direction on this one so I'll mark your answer as the correct one.
jjclarkson
The necessary work has already been done - see my answer on term_expect.
Colin Macleod
A: 

To debug output of my ERP I found I could use exp_internal to get output characters.

exp_internal -f file 0

The output of that gave me: (my number entered being 076338)

spawn id exp0 sent <0>^M
spawn id exp6 sent <0>^M
spawn id exp0 sent <7>^M
spawn id exp6 sent <7>^M
spawn id exp0 sent <6>^M
spawn id exp6 sent <6>^M
spawn id exp0 sent <3>^M
spawn id exp6 sent <3>^M
spawn id exp0 sent <3>^M
spawn id exp6 sent <3>^M
spawn id exp0 sent <8>^M
spawn id exp6 sent <8>^M
spawn id exp0 sent <\r>^M
spawn id exp6 sent <\r\n\u001b[1;14H>^M

So now I need to figure out the regex to get the field. I had this:

-nobuffer -re {^([a-zA-Z0-9]{1})?[0-9]{5}$} {
    set ordernumber $interact_out(0,string)
}

but now I need to incorporate this:

^([a-zA-Z0-9]{1})?[0-9]{5}

With some regex that would represent this:

\r\n\u001b[1;14H

And then once I have that stored in the $ordernumber variable, I need to somehow isolate just the characters prior to the termination string and store those in a variable.

jjclarkson
I tried {^([a-zA-Z0-9]{1})?[0-9]{5}\r\n\u001b[1;14H$} but got an error I tried throwing some backslashes in there, but I'm just guessing at correct regex syntax...
jjclarkson
A: 

Actually the term_expect example program that comes with Expect can do exactly this. It emulates a cursor-addressable terminal and allows you to test output at specific screen locations. In my ActiveTcl distribution it's in demos/Expect/term_expect.

Colin Macleod