summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornoah <noah@656d521f-e311-0410-88e0-e7920216d269>2007-12-17 13:44:19 +0000
committernoah <noah@656d521f-e311-0410-88e0-e7920216d269>2007-12-17 13:44:19 +0000
commitdf621db8917af7cae7d29e3e5e6cceb135a3d478 (patch)
treef4d15c5581058e2edb00a7103364bff04dd3d134
parenta649ad5164ed9fa6d3ba0b536b8bf4e94adf33ec (diff)
downloadpexpect-df621db8917af7cae7d29e3e5e6cceb135a3d478.tar.gz
Fixed websync. cleaned up examples.
git-svn-id: http://pexpect.svn.sourceforge.net/svnroot/pexpect/trunk@498 656d521f-e311-0410-88e0-e7920216d269
-rwxr-xr-xpexpect/examples/astat.py4
-rwxr-xr-xpexpect/examples/bd_client.py4
-rwxr-xr-xpexpect/examples/bd_serv.py58
-rwxr-xr-xpexpect/examples/chess.py2
-rwxr-xr-xpexpect/examples/chess2.py2
-rwxr-xr-xpexpect/examples/chess3.py2
-rwxr-xr-xpexpect/examples/df.py15
-rwxr-xr-xpexpect/examples/fix_cvs_files.py54
-rwxr-xr-xpexpect/examples/ftp.py13
-rwxr-xr-xpexpect/examples/monitor.py12
-rwxr-xr-xpexpect/examples/passmass.py11
-rwxr-xr-xpexpect/examples/python.py6
-rwxr-xr-xpexpect/examples/rippy.py2
-rwxr-xr-xpexpect/examples/ssh_session.py8
-rwxr-xr-xpexpect/examples/ssh_tunnel.py30
-rwxr-xr-xpexpect/tools/websync.py6
16 files changed, 143 insertions, 86 deletions
diff --git a/pexpect/examples/astat.py b/pexpect/examples/astat.py
index 288c948..82fa3c6 100755
--- a/pexpect/examples/astat.py
+++ b/pexpect/examples/astat.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+
"""This runs Apache Status on the remote host and returns the number of requests per second.
./astat.py [-s server_hostname] [-u username] [-p password]
@@ -11,15 +12,18 @@ Example:
./astat.py -s www.example.com -u mylogin -p mypassword
"""
+
import os, sys, time, re, getopt, getpass
import traceback
import pexpect, pxssh
def exit_with_usage():
+
print globals()['__doc__']
os._exit(1)
def main():
+
######################################################################
## Parse the options, arguments, get ready, etc.
######################################################################
diff --git a/pexpect/examples/bd_client.py b/pexpect/examples/bd_client.py
index 2cac791..564739a 100755
--- a/pexpect/examples/bd_client.py
+++ b/pexpect/examples/bd_client.py
@@ -1,4 +1,8 @@
#!/usr/bin/env python
+
+"""This is a very simple client for the backdoor daemon. This is intended more
+for testing rather than normal use. See bd_serv.py """
+
import socket
import sys, time, select
diff --git a/pexpect/examples/bd_serv.py b/pexpect/examples/bd_serv.py
index a25c20b..b7def9e 100755
--- a/pexpect/examples/bd_serv.py
+++ b/pexpect/examples/bd_serv.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+
"""Back door shell server
This exposes an shell terminal on a socket.
@@ -9,6 +10,7 @@ This exposes an shell terminal on a socket.
--port : set the local port for the server to listen on
--watch : show the virtual screen after each client request
"""
+
# Having the password on the command line is not a good idea, but
# then this entire project is probably not the most security concious thing
# I've ever built. This should be considered an experimental tool -- at best.
@@ -16,33 +18,43 @@ import pxssh, pexpect, ANSI
import time, sys, os, getopt, getpass, traceback, threading, socket
def exit_with_usage(exit_code=1):
+
print globals()['__doc__']
os._exit(exit_code)
class roller (threading.Thread):
+
"""This runs a function in a loop in a thread."""
+
def __init__(self, interval, function, args=[], kwargs={}):
+
"""The interval parameter defines time between each call to the function.
"""
+
threading.Thread.__init__(self)
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.finished = threading.Event()
+
def cancel(self):
+
"""Stop the roller."""
+
self.finished.set()
+
def run(self):
+
while not self.finished.isSet():
# self.finished.wait(self.interval)
self.function(*self.args, **self.kwargs)
def endless_poll (child, prompt, screen, refresh_timeout=0.1):
- """This keeps the screen updated with the output of the child.
- This runs in a separate thread.
- See roller().
- """
+
+ """This keeps the screen updated with the output of the child. This runs in
+ a separate thread. See roller(). """
+
#child.logfile_read = screen
try:
s = child.read_nonblocking(4000, 0.1)
@@ -58,12 +70,13 @@ def endless_poll (child, prompt, screen, refresh_timeout=0.1):
# pass
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
- '''This forks the current process into a daemon.
- Almost none of this is necessary (or advisable) if your daemon
- is being started by inetd. In that case, stdin, stdout and stderr are
- all set up for you to refer to the network connection, and the fork()s
- and session manipulation should not be done (to avoid confusing inetd).
- Only the chdir() and umask() steps remain as useful.
+
+ '''This forks the current process into a daemon. Almost none of this is
+ necessary (or advisable) if your daemon is being started by inetd. In that
+ case, stdin, stdout and stderr are all set up for you to refer to the
+ network connection, and the fork()s and session manipulation should not be
+ done (to avoid confusing inetd). Only the chdir() and umask() steps remain
+ as useful.
References:
UNIX Programming FAQ
@@ -73,14 +86,12 @@ def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
Advanced Programming in the Unix Environment
W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.
- The stdin, stdout, and stderr arguments are file names that
- will be opened and be used to replace the standard file descriptors
- in sys.stdin, sys.stdout, and sys.stderr.
- These arguments are optional and default to /dev/null.
- Note that stderr is opened unbuffered, so
- if it shares a file with stdout then interleaved output
- may not appear in the order that you expect.
- '''
+ The stdin, stdout, and stderr arguments are file names that will be opened
+ and be used to replace the standard file descriptors in sys.stdin,
+ sys.stdout, and sys.stderr. These arguments are optional and default to
+ /dev/null. Note that stderr is opened unbuffered, so if it shares a file
+ with stdout then interleaved output may not appear in the order that you
+ expect. '''
# Do first fork.
try:
@@ -119,10 +130,12 @@ def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
return 0
def add_cursor_blink (response, row, col):
+
i = (row-1) * 80 + col
return response[:i]+'<img src="http://www.noah.org/cursor.gif">'+response[i:]
def main ():
+
try:
optlist, args = getopt.getopt(sys.argv[1:], 'h?d', ['help','h','?', 'hostname=', 'username=', 'password=', 'port=', 'watch'])
except Exception, e:
@@ -243,12 +256,15 @@ def main ():
print "done!"
def pretty_box (rows, cols, s):
+
"""This puts an ASCII text box around the given string, s.
"""
+
top_bot = '+' + '-'*cols + '+\n'
return top_bot + '\n'.join(['|'+line+'|' for line in s.split('\n')]) + '\n' + top_bot
def error_response (msg):
+
response = []
response.append ("""All commands start with :
:{REQUEST} {ARGUMENT}
@@ -268,12 +284,13 @@ is equivalent to:
return '\n'.join(response)
def parse_host_connect_string (hcs):
+
"""This parses a host connection string in the form
username:password@hostname:port. All fields are options expcet hostname. A
dictionary is returned with all four keys. Keys that were not included are
set to empty strings ''. Note that if your password has the '@' character
- then you must backslash escape it.
- """
+ then you must backslash escape it. """
+
if '@' in hcs:
p = re.compile (r'(?P<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)')
else:
@@ -284,6 +301,7 @@ def parse_host_connect_string (hcs):
return d
if __name__ == "__main__":
+
try:
start_time = time.time()
print time.asctime()
diff --git a/pexpect/examples/chess.py b/pexpect/examples/chess.py
index c760433..8c32cf7 100755
--- a/pexpect/examples/chess.py
+++ b/pexpect/examples/chess.py
@@ -1,7 +1,9 @@
#!/usr/bin/env python
+
'''This demonstrates controlling a screen oriented application (curses).
It starts two instances of gnuchess and then pits them against each other.
'''
+
import pexpect
import string
import ANSI
diff --git a/pexpect/examples/chess2.py b/pexpect/examples/chess2.py
index e4378b3..c62d5ce 100755
--- a/pexpect/examples/chess2.py
+++ b/pexpect/examples/chess2.py
@@ -1,7 +1,9 @@
#!/usr/bin/env python
+
'''This demonstrates controlling a screen oriented application (curses).
It starts two instances of gnuchess and then pits them against each other.
'''
+
import pexpect
import string
import ANSI
diff --git a/pexpect/examples/chess3.py b/pexpect/examples/chess3.py
index 286a8e3..4404442 100755
--- a/pexpect/examples/chess3.py
+++ b/pexpect/examples/chess3.py
@@ -1,7 +1,9 @@
#!/usr/bin/env python
+
'''This demonstrates controlling a screen oriented application (curses).
It starts two instances of gnuchess and then pits them against each other.
'''
+
import pexpect
import string
import ANSI
diff --git a/pexpect/examples/df.py b/pexpect/examples/df.py
index 38115c8..64bbf93 100755
--- a/pexpect/examples/df.py
+++ b/pexpect/examples/df.py
@@ -1,11 +1,12 @@
#!/usr/bin/env python
-"""This collects filesystem capacity info using the 'df' command.
-Tuples of filesystem name and percentage are stored in a list.
-A simple report is printed. Filesystems over 95% capacity are highlighted.
-Note that this does not parse filesystem names after the first space, so
-names with spaces in them will be truncated. This will produce ambiguous
-results for automount filesystems on Apple OSX.
-"""
+
+"""This collects filesystem capacity info using the 'df' command. Tuples of
+filesystem name and percentage are stored in a list. A simple report is
+printed. Filesystems over 95% capacity are highlighted. Note that this does not
+parse filesystem names after the first space, so names with spaces in them will
+be truncated. This will produce ambiguous results for automount filesystems on
+Apple OSX. """
+
import pexpect
child = pexpect.spawn ('df')
diff --git a/pexpect/examples/fix_cvs_files.py b/pexpect/examples/fix_cvs_files.py
index 75b266b..e75a149 100755
--- a/pexpect/examples/fix_cvs_files.py
+++ b/pexpect/examples/fix_cvs_files.py
@@ -1,30 +1,32 @@
#!/usr/bin/env python
-"""This is for cleaning up binary files improperly added to CVS.
-This script scans the given path to find binary files;
-checks with CVS to see if the sticky options are set to -kb;
-finally if sticky options are not -kb then uses 'cvs admin' to
-set the -kb option.
-This script ignores CVS directories, symbolic links,
-and files not known under CVS control (cvs status is 'Unknown').
+"""This is for cleaning up binary files improperly added to CVS. This script
+scans the given path to find binary files; checks with CVS to see if the sticky
+options are set to -kb; finally if sticky options are not -kb then uses 'cvs
+admin' to set the -kb option.
-Run this on a CHECKED OUT module sandbox, not on the repository itself.
-After if fixes the sticky options on any files you should manually do
-a 'cvs commit' to accept the changes. Then be sure to have all users do
-a 'cvs up -A' to update the Sticky Option status.
+This script ignores CVS directories, symbolic links, and files not known under
+CVS control (cvs status is 'Unknown').
+
+Run this on a CHECKED OUT module sandbox, not on the repository itself. After
+if fixes the sticky options on any files you should manually do a 'cvs commit'
+to accept the changes. Then be sure to have all users do a 'cvs up -A' to
+update the Sticky Option status.
Noah Spurrier
20030426
"""
+
import os, sys, time
import pexpect
VERBOSE = 1
def is_binary (filename):
- """Assume that any file with a character where
- the 8th bit is set is binary.
- """
+
+ """Assume that any file with a character where the 8th bit is set is
+ binary. """
+
fin = open(filename, 'rb')
wholething = fin.read()
fin.close()
@@ -34,11 +36,11 @@ def is_binary (filename):
return 0
def is_kb_sticky (filename):
- """This checks if 'cvs status' reports '-kb' for Sticky options.
- If the Sticky Option status is '-ks' then this returns 1.
- If the status is 'Unknown' then it returns 1.
- Otherwise 0 is returned.
- """
+
+ """This checks if 'cvs status' reports '-kb' for Sticky options. If the
+ Sticky Option status is '-ks' then this returns 1. If the status is
+ 'Unknown' then it returns 1. Otherwise 0 is returned. """
+
try:
s = pexpect.spawn ('cvs status %s' % filename)
i = s.expect (['Sticky Options:\s*(.*)\r\n', 'Status: Unknown'])
@@ -56,18 +58,19 @@ def is_kb_sticky (filename):
return 0
def cvs_admin_kb (filename):
- """This uses 'cvs admin' to set the '-kb' sticky option.
- """
+
+ """This uses 'cvs admin' to set the '-kb' sticky option. """
+
s = pexpect.run ('cvs admin -kb %s' % filename)
# There is a timing issue. If I run 'cvs admin' too quickly
# cvs sometimes has trouble obtaining the directory lock.
time.sleep(1)
def walk_and_clean_cvs_binaries (arg, dirname, names):
- """This contains the logic for processing files.
- This is the os.path.walk callback.
- This skips dirnames that end in CVS.
- """
+
+ """This contains the logic for processing files. This is the os.path.walk
+ callback. This skips dirnames that end in CVS. """
+
if len(dirname)>3 and dirname[-3:]=='CVS':
return
for n in names:
@@ -80,6 +83,7 @@ def walk_and_clean_cvs_binaries (arg, dirname, names):
cvs_admin_kb (fullpath)
def main ():
+
if len(sys.argv) == 1:
root = '.'
else:
diff --git a/pexpect/examples/ftp.py b/pexpect/examples/ftp.py
index 489d8c2..89a502e 100755
--- a/pexpect/examples/ftp.py
+++ b/pexpect/examples/ftp.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-"""This demonstrates an FTP "bookmark".
-This connects to an ftp site; does a few ftp stuff; and then gives the user
-interactive control over the session. In this case the "bookmark" is to a
-directory on the OpenBSD ftp server. It puts you in the i386 packages
-directory. You can easily modify this for other sites.
+
+"""This demonstrates an FTP "bookmark". This connects to an ftp site; does a
+few ftp stuff; and then gives the user interactive control over the session. In
+this case the "bookmark" is to a directory on the OpenBSD ftp server. It puts
+you in the i386 packages directory. You can easily modify this for other sites.
"""
+
import pexpect
import sys
@@ -33,7 +34,6 @@ child.interact() # Escape character defaults to ^]
# At this point the script is running again.
print 'Left interactve mode.'
-#
# The rest is not strictly necessary. This just demonstrates a few functions.
# This makes sure the child is dead; although it would be killed when Python exits.
if child.isalive():
@@ -45,4 +45,3 @@ if child.isalive():
else:
print 'Child exited gracefully.'
-
diff --git a/pexpect/examples/monitor.py b/pexpect/examples/monitor.py
index ed17a58..e31b51b 100755
--- a/pexpect/examples/monitor.py
+++ b/pexpect/examples/monitor.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python
-""" monitor.py
- This runs a sequence of commands on a remote host using SSH.
- It runs a simple system checks such as uptime and free to monitor
- the state of the remote host.
+
+""" This runs a sequence of commands on a remote host using SSH. It runs a
+simple system checks such as uptime and free to monitor the state of the remote
+host.
./monitor.py [-s server_hostname] [-u username] [-p password]
-s : hostname of the remote server to login to.
@@ -22,6 +22,7 @@ It works like this:
Run 'free'.
Exit the remote host.
"""
+
import os, sys, time, re, getopt, getpass
import traceback
import pexpect
@@ -36,10 +37,12 @@ TERMINAL_TYPE = 'vt100'
SSH_NEWKEY = '(?i)are you sure you want to continue connecting'
def exit_with_usage():
+
print globals()['__doc__']
os._exit(1)
def main():
+
global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY
######################################################################
## Parse the options, arguments, get ready, etc.
@@ -195,6 +198,7 @@ def main():
child.expect(EOF)
if __name__ == "__main__":
+
try:
main()
except Exception, e:
diff --git a/pexpect/examples/passmass.py b/pexpect/examples/passmass.py
index bd792e7..b1e17b9 100755
--- a/pexpect/examples/passmass.py
+++ b/pexpect/examples/passmass.py
@@ -1,8 +1,7 @@
#!/usr/bin/env python
-'''Change passwords on the named machines.
- passmass host1 host2 host3 . . .
-Note that login shell prompt on remote machine must end in # or $.
-'''
+
+"""Change passwords on the named machines. passmass host1 host2 host3 . . .
+Note that login shell prompt on remote machine must end in # or $. """
import pexpect
import sys, getpass
@@ -12,7 +11,9 @@ COMMAND_PROMPT = '[$#] '
TERMINAL_PROMPT = r'Terminal type\?'
TERMINAL_TYPE = 'vt100'
SSH_NEWKEY = r'Are you sure you want to continue connecting \(yes/no\)\?'
+
def login(host, user, password):
+
child = pexpect.spawn('ssh -l %s %s'%(user, host))
fout = file ("LOG.TXT","wb")
child.setlog (fout)
@@ -40,6 +41,7 @@ def login(host, user, password):
# (current) UNIX password:
def change_password(child, user, oldpassword, newpassword):
+
child.sendline('passwd')
i = child.expect(['[Oo]ld [Pp]assword', '.current.*password', '[Nn]ew [Pp]assword'])
# Root does not require old password, so it gets to bypass the next step.
@@ -57,6 +59,7 @@ def change_password(child, user, oldpassword, newpassword):
child.sendline(newpassword)
def main():
+
if len(sys.argv) <= 1:
print USAGE
return 1
diff --git a/pexpect/examples/python.py b/pexpect/examples/python.py
index 22b541e..d8c9866 100755
--- a/pexpect/examples/python.py
+++ b/pexpect/examples/python.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
-'''This starts the python interpreter; captures the startup message; then gives the user interactive control over the session.
-Why?
-'''
+
+"""This starts the python interpreter; captures the startup message; then gives
+the user interactive control over the session. Why? For fun... """
# Don't do this unless you like being John Malkovich
# c = pexpect.spawn ('/usr/bin/env python ./python.py')
diff --git a/pexpect/examples/rippy.py b/pexpect/examples/rippy.py
index c881e37..e5b1c6a 100755
--- a/pexpect/examples/rippy.py
+++ b/pexpect/examples/rippy.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+
"""Rippy!
This script helps to convert video from one format to another.
@@ -67,6 +68,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
Noah Spurrier
$Id$
"""
+
import sys, os, re, math, stat, getopt, traceback, types, time
import pexpect
diff --git a/pexpect/examples/ssh_session.py b/pexpect/examples/ssh_session.py
index 6ff04aa..4d0e228 100755
--- a/pexpect/examples/ssh_session.py
+++ b/pexpect/examples/ssh_session.py
@@ -10,8 +10,11 @@ import getpass
import time
class ssh_session:
+
"Session with extra state including the password to be used."
+
def __init__(self, user, host, password=None, verbose=0):
+
self.user = user
self.host = host
self.verbose = verbose
@@ -27,6 +30,7 @@ class ssh_session:
self.f = open('ssh.out','w')
def __repr__(self):
+
outl = 'class :'+self.__class__.__name__
for attr in self.__dict__:
if attr == 'password':
@@ -36,6 +40,7 @@ class ssh_session:
return outl
def __exec(self, command):
+
"Execute a command on the remote host. Return the output."
child = spawn(command,
#timeout=10,
@@ -69,14 +74,17 @@ class ssh_session:
return child.before
def ssh(self, command):
+
return self.__exec("ssh -l %s %s \"%s\"" \
% (self.user,self.host,command))
def scp(self, src, dst):
+
return self.__exec("scp %s %s@%s:%s" \
% (src, session.user, session.host, dst))
def exists(self, file):
+
"Retrieve file permissions of specified remote file."
seen = self.ssh("/bin/ls -ld %s" % file)
if string.find(seen, "No such file") > -1:
diff --git a/pexpect/examples/ssh_tunnel.py b/pexpect/examples/ssh_tunnel.py
index f665d01..3c8bc09 100755
--- a/pexpect/examples/ssh_tunnel.py
+++ b/pexpect/examples/ssh_tunnel.py
@@ -1,17 +1,18 @@
#!/usr/bin/env python
-"""This starts an SSH tunnel to a given host.
-If the SSH process ever dies then this script will detect that and restart it.
-I use this under Cygwin to keep open encrypted tunnels to
-port 25 (SMTP), port 143 (IMAP4), and port 110 (POP3). I set my mail client to talk to
-localhost and I keep this script running in the background.
-Note that this is a rather stupid script at the moment because it
-just looks to see if any ssh process is running. It should really
-make sure that our specific ssh process is running.
-ssh is missing a very useful feature. It has no way to report the
-process id of the background daemon that it creates with the -f command.
-This would be a really useful script if I could figure a way around this problem.
-"""
+"""This starts an SSH tunnel to a given host. If the SSH process ever dies then
+this script will detect that and restart it. I use this under Cygwin to keep
+open encrypted tunnels to port 25 (SMTP), port 143 (IMAP4), and port 110
+(POP3). I set my mail client to talk to localhost and I keep this script
+running in the background.
+
+Note that this is a rather stupid script at the moment because it just looks to
+see if any ssh process is running. It should really make sure that our specific
+ssh process is running. The problem is that ssh is missing a very useful
+feature. It has no way to report the process id of the background daemon that
+it creates with the -f command. This would be a really useful script if I could
+figure a way around this problem. """
+
import pexpect
import getpass
import time
@@ -23,7 +24,9 @@ user = raw_input('Username: ')
X = getpass.getpass('Password: ')
def get_process_info ():
+
# This seems to work on both Linux and BSD, but should otherwise be considered highly UNportable.
+
ps = pexpect.run ('ps ax -O ppid')
pass
def start_tunnel ():
@@ -39,7 +42,8 @@ def start_tunnel ():
print str(e)
def main ():
- while 1:
+
+ while True:
ps = pexpect.spawn ('ps')
time.sleep (1)
index = ps.expect (['/usr/bin/ssh', pexpect.EOF, pexpect.TIMEOUT])
diff --git a/pexpect/tools/websync.py b/pexpect/tools/websync.py
index 311b935..d1c6af4 100755
--- a/pexpect/tools/websync.py
+++ b/pexpect/tools/websync.py
@@ -13,14 +13,14 @@ import sys, os
X = getpass.getpass('Password: ')
pp_pattern=["(?i)password:", "(?i)enter passphrase for key '.*?':"]
-p = pexpect.spawn ('scp -r doc/. noah@shell.sourceforge.net:htdocs/.')
+p = pexpect.spawn ('scp -r doc/. noah@shell.sourceforge.net:/home/groups/p/pe/pexpect/htdocs/.')
p.logfile = sys.stdout
p.expect (pp_pattern)
p.sendline (X)
p.expect (pexpect.EOF)
print p.before
-p = pexpect.spawn ('scp doc/clean.css doc/email.png noah@shell.sourceforge.net:htdocs/clean.css')
+p = pexpect.spawn ('scp doc/clean.css doc/email.png noah@shell.sourceforge.net:/home/groups/p/pe/pexpect/htdocs/clean.css')
p.logfile = sys.stdout
p.expect (pp_pattern)
p.sendline (X)
@@ -34,7 +34,7 @@ print p.before
#p.expect (pexpect.EOF)
#print p.before
-p = pexpect.spawn ('scp dist/pexpect-*.tar.gz noah@shell.sourceforge.net:htdocs/.')
+p = pexpect.spawn ('scp dist/pexpect-*.tar.gz noah@shell.sourceforge.net:/home/groups/p/pe/pexpect/htdocs/.')
p.logfile = sys.stdout
p.expect (pp_pattern)
p.sendline (X)