summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornoah <noah@656d521f-e311-0410-88e0-e7920216d269>2007-12-19 03:00:33 +0000
committernoah <noah@656d521f-e311-0410-88e0-e7920216d269>2007-12-19 03:00:33 +0000
commitc0a3518dd5f0b7278972ac050f881e52415ba103 (patch)
treea1bb32ceb3d2241cd36f199812301127dae08bfe
parentde5c6b824f3c1a4bcca3ee36db0fd16bfc7be77d (diff)
downloadpexpect-c0a3518dd5f0b7278972ac050f881e52415ba103.tar.gz
Adding waitnoecho and test functions.
git-svn-id: http://pexpect.svn.sourceforge.net/svnroot/pexpect/trunk@501 656d521f-e311-0410-88e0-e7920216d269
-rw-r--r--pexpect/README3
-rw-r--r--pexpect/pexpect.py41
-rwxr-xr-xpexpect/tests/echo_wait.py19
-rwxr-xr-xpexpect/tests/test_expect.py13
4 files changed, 72 insertions, 4 deletions
diff --git a/pexpect/README b/pexpect/README
index 98cd631..3101dc8 100644
--- a/pexpect/README
+++ b/pexpect/README
@@ -16,6 +16,9 @@ Python, Pexpect does not require TCL or Expect nor does it require C
extensions to be compiled. It should work on any platform that supports the
standard Python pty module. The Pexpect interface was designed to be easy to use.
+If you want to work with the development version of the source code then please
+read the DEVELOPERS document in the root of the source code tree.
+
Free, open source, and all that good stuff.
Pexpect Copyright (c) 2008 Noah Spurrier
diff --git a/pexpect/pexpect.py b/pexpect/pexpect.py
index fbac205..cb4dd20 100644
--- a/pexpect/pexpect.py
+++ b/pexpect/pexpect.py
@@ -670,6 +670,40 @@ class spawn (object):
return os.isatty(self.child_fd)
+ def waitnoecho (self, timeout=-1):
+
+ """This waits until the terminal ECHO flag is set False. This returns
+ True if the echo mode is off. This returns False if the ECHO flag was
+ not set False before the timeout. This can be used to detect when the
+ child is waiting for a password. Usually a child application will turn
+ off echo mode when it is waiting for the user to enter a password. It
+ timeout is None then this method to block forever until ECHO flag is
+ False."""
+
+ if timeout == -1:
+ timeout = self.timeout
+ if timeout is not None:
+ end_time = time.time() + timeout
+ while True:
+ if not self.getecho():
+ return True
+ if timeout < 0 and timeout is not None:
+ return False
+ if timeout is not None:
+ timeout = end_time - time.time()
+ time.sleep(0.1)
+
+ def getecho (self):
+
+ """This returns the terminal echo mode. This returns True if echo is
+ on or False if echo is off. Child applications that are expecting you
+ to enter a password often set ECHO False. See waitnoecho(). """
+
+ attr = termios.tcgetattr(self.child_fd)
+ if attr[3] & termios.ECHO:
+ return True
+ return False
+
def setecho (self, state):
"""This sets the terminal echo mode on or off. Note that anything the
@@ -702,11 +736,11 @@ class spawn (object):
"""
self.child_fd
- new = termios.tcgetattr(self.child_fd)
+ attr = termios.tcgetattr(self.child_fd)
if state:
- new[3] = new[3] | termios.ECHO
+ attr[3] = attr[3] | termios.ECHO
else:
- new[3] = new[3] & ~termios.ECHO
+ attr[3] = attr[3] & ~termios.ECHO
# I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent
# and blocked on some platforms. TCSADRAIN is probably ideal if it worked.
termios.tcsetattr(self.child_fd, termios.TCSANOW, new)
@@ -1778,4 +1812,3 @@ def split_command_line(command_line):
return arg_list
# vi:ts=4:sw=4:expandtab:ft=python:
-
diff --git a/pexpect/tests/echo_wait.py b/pexpect/tests/echo_wait.py
new file mode 100755
index 0000000..2d27991
--- /dev/null
+++ b/pexpect/tests/echo_wait.py
@@ -0,0 +1,19 @@
+import signal, time, struct, fcntl, termios, os, sys
+
+# a dumb PAM will print the password prompt first then set ECHO
+# False. What it should do it set ECHO False first then print the
+# prompt. Otherwise, if we see the password prompt and type out
+# password real fast before it turns off ECHO then some or all of
+# our password might be visibly echod back to us. Sounds unlikely?
+# It happens.
+
+print "fake password:"
+sys.stdout.flush()
+attr = termios.tcgetattr(sys.stdout)
+attr[3] = attr[3] & ~termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, new)
+time.sleep(3)
+attr[3] = attr[3] | termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, new)
+
+time.sleep(20)
diff --git a/pexpect/tests/test_expect.py b/pexpect/tests/test_expect.py
index 3afef87..3929192 100755
--- a/pexpect/tests/test_expect.py
+++ b/pexpect/tests/test_expect.py
@@ -109,6 +109,19 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
index = p.expect ([pexpect.EOF,'abcd','wxyz','7890'])
assert index == 3, "index="+str(index)
+ def test_waitnoecho (self):
+
+ """ This tests that we can wait on a child process to set echo mode.
+ For example, this tests that we could wait for SSH to set ECHO False
+ when asking of a password. This makes use of an external script
+ echo_wait.py. """
+
+ p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN)
+ start = time.time()
+ p1.waitnoecho(timeout=10)
+ end_time = time.time() - start
+ assert end_time < 10 and end_time > 2, "waitnoecho did not set ECHO off in the expected time window"
+
def test_expect_echo (self):
"""This tests that echo can be turned on and off.
"""