expect module

Jose M. Pereira (pereira@qual.inesc.pt)
Fri, 5 Aug 94 20:21:42 +0200

>>>>> "Michael" == Michael McLay <mclay@eeel.nist.gov> wrote:

Michael> Are you planning to post the expect module to the net? I have a
Michael> friend down the hall that will find this module interesting.

Yes. Ahem. Really should have thought of some innocuous, context free
name. :-)

I did thought of using TCL-based "expect" first, then I realized I didn't need
anything so sophisticated, and it would be nice to be directly usable from
Python. So, I just wrote a little module (".py"), nothing fancy, really, as
you see from:

>> BTW, I just made an "expect" module to IPC, using plain simple
>> pipes. It does fork & exec a given program passing some file
>> descriptors (could be sockets).

Or pty's, which indeed would come a little closer to the real "expect"
program!

Of course, if you really want a full-blown expect functionality, just use
libexpect(3) interface to construct a Python C module!

Yeah, now that you (I) mention it... That's really easy... Full expect scripts
using Python... if someone cajoles me into it... Ok, as soon as I get some
free time... <:-}

(For the time being, and given the overwhelming interest, I can post the full
73 lines of undocumented, self-explainable, QuickPython(c) hacks I've made.
See below.)

Michael> National Institute of Standards and Technology

NIST? OK, do you by any chance know anyone called Don Libes ?-)

Cheers,
Jose'

--cut--
# expect.py ############## should be "something completely different", but
########################## that's too long
# Caveat emptor! Be careful with deadlocks, uncomplete inputs, etc.!
# should only work in unix (?)
# Author: jmp@inesc.pt (7/94)
import sys
import os

class SubProcess:
def __init__(self, prog,*args):
rp, wc = os.pipe() # stdin
rc, wp = os.pipe() # stdout
ec, ep = os.pipe() # stderr
self.pid = os.fork()
if self.pid: #parent
os.close(rc)
#Try to flush this! os.close(wc)
self.inf = os.fdopen(rp, 'r')
self.outf = os.fdopen(wp, 'w')
self.errf = os.fdopen(ep, 'r')
self.inf_write = os.fdopen(wc, 'r') # does it work??
else: #child
os.close(rp)
os.close(wp)
os.close(ep)
os.dup2(rc, 0) #sys.stdin = rc
os.dup2(wc, 1) #sys.stdout = wc
os.dup2(ec, 2) #sys.stderr = ec
#os.execv(prog, args)
os.execvp(prog, args)
raise 'should not get here'

def __del__(self): #kill child
os.kill(self.pid, 1)
print 'Killed', os.waitpid(self.pid, 0)

from select import select

def write(self, line):
if self.select([],[self.outf],[],0)[1] != []:
self.outf.write(line)
else: raise posix.IOError
self.outf.flush()

# should this be named "readline"?
def read(self):
self.inf_write.flush() #????
if self.select([self.inf],[],[],0)[0] != []:
return self.inf.readline()
else: self.inf.flush(); return None

def readlines(self):
lines = []
line = self.read()
while line != None:
lines.append(line)
line = self.read()
lines.append(self.inf.readline()) # One off????
return lines

import regex
def expect(self, patt):
# Reads lines from subproc. until one matches regex patt
matched = -1
lines = []
while matched < 0: #get more
reply = self.inf.readline() # ARGH
lines.append(reply)
matched = self.regex.match(patt, reply)
return matched, reply, lines

def test():
x=SubProcess('/bin/cat')
x.outf.write('first\n')
x.outf.write('second\n')
print x.inf.readline()
print x.inf.readline()