"Fossies" - the Fresh Open Source Software Archive

Member "sshexport-2.5/sshexport" (20 Sep 2021, 90123 Bytes) of package /linux/privat/sshexport-2.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "sshexport": 2.4_vs_2.5.

    1 #!/usr/bin/env python3
    2 #
    3 # sshexport -- prepare a remote account for ssh access
    4 #
    5 # SPDX-License-Identifier: BSD-2-clause
    6 #
    7 # This code runs under both Python 2 and Python 3. Preserve this property!
    8 from __future__ import print_function
    9 
   10 """This script tries to export ssh public keys to a specified site.  It will
   11 walk you through generating key pairs if it doesn't find any to export.
   12 It handles all the fiddly details like making sure local and remote
   13 permissions are correct, and tells you what it's doing if it has to change
   14 anything.
   15 
   16 Options:
   17 -h        Print usage summary and exit
   18 -c        Check local and remote configuration only, don't try to fix problems.
   19 -d        Delete remote .ssh configuration.
   20 -r        Install keys on all sites in the saved list.
   21 -v        Report all commands sent to host and output received.
   22 -p <port> Connect on a particular port in place of 22
   23 
   24 Author: Eric S. Raymond <esr@thyrsus.com>"""
   25 
   26 import os, stat, sys, getopt, getpass, tempfile
   27 
   28 try:
   29     import configparser
   30 except ImportError:
   31     import ConfigParser as configparser
   32 
   33 ###############################################################################
   34 #
   35 # pexpect 2.3 is inlined here because it's not in the Python library yet.
   36 #
   37 # SPDX-License-Identifier: ISC
   38 
   39 """Pexpect is a Python module for spawning child applications and controlling
   40 them automatically. Pexpect can be used for automating interactive applications
   41 such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
   42 scripts for duplicating software package installations on different servers. It
   43 can be used for automated software testing. Pexpect is in the spirit of Don
   44 Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
   45 require TCL and Expect or require C extensions to be compiled. Pexpect does not
   46 use C, Expect, or TCL extensions. It should work on any platform that supports
   47 the standard Python pty module. The Pexpect interface focuses on ease of use so
   48 that simple tasks are easy.
   49 
   50 There are two main interfaces to Pexpect -- the function, run() and the class,
   51 spawn. You can call the run() function to execute a command and return the
   52 output. This is a handy replacement for os.system().
   53 
   54 For example::
   55 
   56     pexpect.run('ls -la')
   57 
   58 The more powerful interface is the spawn class. You can use this to spawn an
   59 external child command and then interact with the child by sending lines and
   60 expecting responses.
   61 
   62 For example::
   63 
   64     child = pexpect.spawn('scp foo myname@host.example.com:.')
   65     child.expect ('Password:')
   66     child.sendline (mypassword)
   67 
   68 This works even for commands that ask for passwords or other input outside of
   69 the normal stdio streams.
   70 
   71 Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
   72 Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
   73 vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
   74 Geoffrey Marshall, Francisco Lourenco, Glen Mabey, Karthik Gurusamy, Fernando
   75 Perez, Corey Minyard, Jon Cohen, Guillaume Chazarain, Andrew Ryan, Nick
   76 Craig-Wood, Andrew Stone, Jorgen Grahn (Let me know if I forgot anyone.)
   77 
   78 Free, open source, and all that good stuff.
   79 
   80 Permission is hereby granted, free of charge, to any person obtaining a copy of
   81 this software and associated documentation files (the "Software"), to deal in
   82 the Software without restriction, including without limitation the rights to
   83 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   84 of the Software, and to permit persons to whom the Software is furnished to do
   85 so, subject to the following conditions:
   86 
   87 The above copyright notice and this permission notice shall be included in all
   88 copies or substantial portions of the Software.
   89 
   90 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   91 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   92 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   93 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   94 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   95 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   96 SOFTWARE.
   97 
   98 Pexpect Copyright (c) 2008 Noah Spurrier
   99 http://pexpect.sourceforge.net/
  100 
  101 $Id: pexpect.py 507 2007-12-27 02:40:52Z noah $
  102 """
  103 
  104 try:
  105     import os, sys, time
  106     import select
  107     import string
  108     import re
  109     import struct
  110     import resource
  111     import types
  112     import pty
  113     import tty
  114     import termios
  115     import fcntl
  116     import errno
  117     import traceback
  118     import signal
  119 except ImportError as e:
  120     raise ImportError(str(e) + """
  121 
  122 A critical module was not found. Probably this operating system does not
  123 support it. Pexpect is intended for UNIX-like operating systems.""")
  124 
  125 __version__ = '2.3'
  126 __revision__ = '$Revision: 399 $'
  127 __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which',
  128     'split_command_line', '__version__', '__revision__']
  129 
  130 # Exception classes used by this module.
  131 class ExceptionPexpect(Exception):
  132 
  133     """Base class for all exceptions raised by this module.
  134     """
  135 
  136     def __init__(self, value):
  137 
  138         Exception.__init__(self)
  139         self.value = value
  140 
  141     def __str__(self):
  142 
  143         return str(self.value)
  144 
  145     def get_trace(self):
  146 
  147         """This returns an abbreviated stack trace with lines that only concern
  148         the caller. In other words, the stack trace inside the Pexpect module
  149         is not included. """
  150 
  151         tblist = traceback.extract_tb(sys.exc_info()[2])
  152         #tblist = filter(self.__filter_not_pexpect, tblist)
  153         tblist = [item for item in tblist if self.__filter_not_pexpect(item)]
  154         tblist = traceback.format_list(tblist)
  155         return ''.join(tblist)
  156 
  157     def __filter_not_pexpect(self, trace_list_item):
  158 
  159         """This returns True if list item 0 the string 'pexpect.py' in it. """
  160 
  161         if trace_list_item[0].find('pexpect.py') == -1:
  162             return True
  163         else:
  164             return False
  165 
  166 class EOF(ExceptionPexpect):
  167 
  168     """Raised when EOF is read from a child. This usually means the child has exited."""
  169 
  170 class TIMEOUT(ExceptionPexpect):
  171 
  172     """Raised when a read time exceeds the timeout. """
  173 
  174 ##class TIMEOUT_PATTERN(TIMEOUT):
  175 ##    """Raised when the pattern match time exceeds the timeout.
  176 ##    This is different than a read TIMEOUT because the child process may
  177 ##    give output, thus never give a TIMEOUT, but the output
  178 ##    may never match a pattern.
  179 ##    """
  180 ##class MAXBUFFER(ExceptionPexpect):
  181 ##    """Raised when a scan buffer fills before matching an expected pattern."""
  182 
  183 def run(command, timeout=-1, withexitstatus=False, events=None, _extra_args=None, logfile=None, cwd=None, env=None):
  184 
  185     """
  186     This function runs the given command; waits for it to finish; then
  187     returns all output as a string. STDERR is included in output. If the full
  188     path to the command is not given then the path is searched.
  189 
  190     Note that lines are terminated by CR/LF (\\r\\n) combination even on
  191     UNIX-like systems because this is the standard for pseudo ttys. If you set
  192     'withexitstatus' to true, then run will return a tuple of (command_output,
  193     exitstatus). If 'withexitstatus' is false then this returns just
  194     command_output.
  195 
  196     The run() function can often be used instead of creating a spawn instance.
  197     For example, the following code uses spawn::
  198 
  199         from pexpect import *
  200         child = spawn('scp foo myname@host.example.com:.')
  201         child.expect ('(?i)password')
  202         child.sendline (mypassword)
  203 
  204     The previous code can be replace with the following::
  205 
  206         from pexpect import *
  207         run ('scp foo myname@host.example.com:.', events={'(?i)password': mypassword})
  208 
  209     Examples
  210     ========
  211 
  212     Start the apache daemon on the local machine::
  213 
  214         from pexpect import *
  215         run ("/usr/local/apache/bin/apachectl start")
  216 
  217     Check in a file using SVN::
  218 
  219         from pexpect import *
  220         run ("svn ci -m 'automatic commit' my_file.py")
  221 
  222     Run a command and capture exit status::
  223 
  224         from pexpect import *
  225         (command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
  226 
  227     Tricky Examples
  228     ===============
  229 
  230     The following will run SSH and execute 'ls -l' on the remote machine. The
  231     password 'secret' will be sent if the '(?i)password' pattern is ever seen::
  232 
  233         run ("ssh username@machine.example.com 'ls -l'", events={'(?i)password':'secret\\n'})
  234 
  235     This will start mencoder to rip a video from DVD. This will also display
  236     progress ticks every 5 seconds as it runs. For example::
  237 
  238         from pexpect import *
  239         def print_ticks(d):
  240             print d['event_count'],
  241         run ("mencoder dvd://1 -o video.avi -oac copy -ovc copy", events={TIMEOUT:print_ticks}, timeout=5)
  242 
  243     The 'events' argument should be a dictionary of patterns and responses.
  244     Whenever one of the patterns is seen in the command out run() will send the
  245     associated response string. Note that you should put newlines in your
  246     string if Enter is necessary. The responses may also contain callback
  247     functions. Any callback is function that takes a dictionary as an argument.
  248     The dictionary contains all the locals from the run() function, so you can
  249     access the child spawn object or any other variable defined in run()
  250     (event_count, child, and extra_args are the most useful). A callback may
  251     return True to stop the current run process otherwise run() continues until
  252     the next event. A callback may also return a string which will be sent to
  253     the child. 'extra_args' is not used by directly run(). It provides a way to
  254     pass data to a callback function through run() through the locals
  255     dictionary passed to a callback. """
  256 
  257     if timeout == -1:
  258         child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env)
  259     else:
  260         child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, cwd=cwd, env=env)
  261     if events is not None:
  262         patterns = list(events.keys())
  263         responses = list(events.values())
  264     else:
  265         patterns = None # We assume that EOF or TIMEOUT will save us.
  266         responses = None
  267     child_result_list = []
  268     event_count = 0
  269     while 1:
  270         try:
  271             index = child.expect(patterns)
  272             if type(child.after) in str:
  273                 child_result_list.append(child.before + child.after)
  274             else: # child.after may have been a TIMEOUT or EOF, so don't cat those.
  275                 child_result_list.append(child.before)
  276             if type(responses[index]) in str:
  277                 child.send(responses[index])
  278             elif type(responses[index]) is types.FunctionType:
  279                 callback_result = responses[index](locals())
  280                 sys.stdout.flush()
  281                 if type(callback_result) in str:
  282                     child.send(callback_result)
  283                 elif callback_result:
  284                     break
  285             else:
  286                 raise TypeError('The callback must be a string or function type.')
  287             event_count = event_count + 1
  288         except TIMEOUT as e:
  289             child_result_list.append(child.before)
  290             break
  291         except EOF as e:
  292             child_result_list.append(child.before)
  293             break
  294     child_result = ''.join(child_result_list)
  295     if withexitstatus:
  296         child.close()
  297         return (child_result, child.exitstatus)
  298     else:
  299         return child_result
  300 
  301 class spawn(object):
  302 
  303     """This is the main class interface for Pexpect. Use this class to start
  304     and control child applications. """
  305 
  306     def __init__(self, command, args=None, timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None):
  307 
  308         """This is the constructor. The command parameter may be a string that
  309         includes a command and any arguments to the command. For example::
  310 
  311             child = pexpect.spawn ('/usr/bin/ftp')
  312             child = pexpect.spawn ('/usr/bin/ssh user@example.com')
  313             child = pexpect.spawn ('ls -latr /tmp')
  314 
  315         You may also construct it with a list of arguments like so::
  316 
  317             child = pexpect.spawn ('/usr/bin/ftp', [])
  318             child = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
  319             child = pexpect.spawn ('ls', ['-latr', '/tmp'])
  320 
  321         After this the child application will be created and will be ready to
  322         talk to. For normal use, see expect() and send() and sendline().
  323 
  324         Remember that Pexpect does NOT interpret shell meta characters such as
  325         redirect, pipe, or wild cards (>, |, or *). This is a common mistake.
  326         If you want to run a command and pipe it through another command then
  327         you must also start a shell. For example::
  328 
  329             child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
  330             child.expect(pexpect.EOF)
  331 
  332         The second form of spawn (where you pass a list of arguments) is useful
  333         in situations where you wish to spawn a command and pass it its own
  334         argument list. This can make syntax more clear. For example, the
  335         following is equivalent to the previous example::
  336 
  337             shell_cmd = 'ls -l | grep LOG > log_list.txt'
  338             child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
  339             child.expect(pexpect.EOF)
  340 
  341         The maxread attribute sets the read buffer size. This is maximum number
  342         of bytes that Pexpect will try to read from a TTY at one time. Setting
  343         the maxread size to 1 will turn off buffering. Setting the maxread
  344         value higher may help performance in cases where large amounts of
  345         output are read back from the child. This feature is useful in
  346         conjunction with searchwindowsize.
  347 
  348         The searchwindowsize attribute sets the how far back in the incomming
  349         seach buffer Pexpect will search for pattern matches. Every time
  350         Pexpect reads some data from the child it will append the data to the
  351         incomming buffer. The default is to search from the beginning of the
  352         imcomming buffer each time new data is read from the child. But this is
  353         very inefficient if you are running a command that generates a large
  354         amount of data where you want to match The searchwindowsize does not
  355         effect the size of the incomming data buffer. You will still have
  356         access to the full buffer after expect() returns.
  357 
  358         The logfile member turns on or off logging. All input and output will
  359         be copied to the given file object. Set logfile to None to stop
  360         logging. This is the default. Set logfile to sys.stdout to echo
  361         everything to standard output. The logfile is flushed after each write.
  362 
  363         Example log input and output to a file::
  364 
  365             child = pexpect.spawn('some_command')
  366             fout = file('mylog.txt','w')
  367             child.logfile = fout
  368 
  369         Example log to stdout::
  370 
  371             child = pexpect.spawn('some_command')
  372             child.logfile = sys.stdout
  373 
  374         The logfile_read and logfile_send members can be used to separately log
  375         the input from the child and output sent to the child. Sometimes you
  376         don't want to see everything you write to the child. You only want to
  377         log what the child sends back. For example::
  378 
  379             child = pexpect.spawn('some_command')
  380             child.logfile_read = sys.stdout
  381 
  382         To separately log output sent to the child use logfile_send::
  383 
  384             self.logfile_send = fout
  385 
  386         The delaybeforesend helps overcome a weird behavior that many users
  387         were experiencing. The typical problem was that a user would expect() a
  388         "Password:" prompt and then immediately call sendline() to send the
  389         password. The user would then see that their password was echoed back
  390         to them. Passwords don't normally echo. The problem is caused by the
  391         fact that most applications print out the "Password" prompt and then
  392         turn off stdin echo, but if you send your password before the
  393         application turned off echo, then you get your password echoed.
  394         Normally this wouldn't be a problem when interacting with a human at a
  395         real keyboard. If you introduce a slight delay just before writing then
  396         this seems to clear up the problem. This was such a common problem for
  397         many users that I decided that the default pexpect behavior should be
  398         to sleep just before writing to the child application. 1/20th of a
  399         second (50 ms) seems to be enough to clear up the problem. You can set
  400         delaybeforesend to 0 to return to the old behavior. Most Linux machines
  401         don't like this to be below 0.03. I don't know why.
  402 
  403         Note that spawn is clever about finding commands on your path.
  404         It uses the same logic that "which" uses to find executables.
  405 
  406         If you wish to get the exit status of the child you must call the
  407         close() method. The exit or signal status of the child will be stored
  408         in self.exitstatus or self.signalstatus. If the child exited normally
  409         then exitstatus will store the exit return code and signalstatus will
  410         be None. If the child was terminated abnormally with a signal then
  411         signalstatus will store the signal value and exitstatus will be None.
  412         If you need more detail you can also read the self.status member which
  413         stores the status returned by os.waitpid. You can interpret this using
  414         os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. """
  415 
  416         self.STDIN_FILENO = pty.STDIN_FILENO
  417         self.STDOUT_FILENO = pty.STDOUT_FILENO
  418         self.STDERR_FILENO = pty.STDERR_FILENO
  419         self.stdin = sys.stdin
  420         self.stdout = sys.stdout
  421         self.stderr = sys.stderr
  422 
  423         self.searcher = None
  424         self.ignorecase = False
  425         self.before = None
  426         self.after = None
  427         self.match = None
  428         self.match_index = None
  429         self.terminated = True
  430         self.exitstatus = None
  431         self.signalstatus = None
  432         self.status = None # status returned by os.waitpid
  433         self.flag_eof = False
  434         self.pid = None
  435         self.child_fd = -1 # initially closed
  436         self.timeout = timeout
  437         self.delimiter = EOF
  438         self.logfile = logfile
  439         self.logfile_read = None # input from child (read_nonblocking)
  440         self.logfile_send = None # output to send (send, sendline)
  441         self.maxread = maxread # max bytes to read at one time into buffer
  442         self.buffer = '' # This is the read buffer. See maxread.
  443         self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
  444         # Most Linux machines don't like delaybeforesend to be below 0.03 (30 ms).
  445         self.delaybeforesend = 0.05 # Sets sleep time used just before sending data to child. Time in seconds.
  446         self.delayafterclose = 0.1 # Sets delay in close() method to allow kernel time to update process status. Time in seconds.
  447         self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
  448         self.softspace = False # File-like object.
  449         self.name = '<' + repr(self) + '>' # File-like object.
  450         self.encoding = None # File-like object.
  451         self.closed = True # File-like object.
  452         self.cwd = cwd
  453         self.env = env
  454         self.__irix_hack = (sys.platform.lower().find('irix') >= 0) # This flags if we are running on irix
  455         # Solaris uses internal __fork_pty(). All others use pty.fork().
  456         if (sys.platform.lower().find('solaris') >= 0) or (sys.platform.lower().find('sunos5') >= 0):
  457             self.use_native_pty_fork = False
  458         else:
  459             self.use_native_pty_fork = True
  460 
  461 
  462         # allow dummy instances for subclasses that may not use command or args.
  463         if command is None:
  464             self.command = None
  465             self.args = None
  466             self.name = '<pexpect factory incomplete>'
  467         else:
  468             self._spawn(command, args)
  469 
  470     def __del__(self):
  471 
  472         """This makes sure that no system resources are left open. Python only
  473         garbage collects Python objects. OS file descriptors are not Python
  474         objects, so they must be handled explicitly. If the child file
  475         descriptor was opened outside of this class (passed to the constructor)
  476         then this does not close it. """
  477 
  478         if not self.closed:
  479             # It is possible for __del__ methods to execute during the
  480             # teardown of the Python VM itself. Thus self.close() may
  481             # trigger an exception because os.close may be None.
  482             # -- Fernando Perez
  483             try:
  484                 self.close()
  485             except AttributeError:
  486                 pass
  487 
  488     def __str__(self):
  489 
  490         """This returns a human-readable string that represents the state of
  491         the object. """
  492 
  493         s = []
  494         s.append(repr(self))
  495         s.append('version: ' + __version__ + ' (' + __revision__ + ')')
  496         s.append('command: ' + str(self.command))
  497         s.append('args: ' + str(self.args))
  498         s.append('searcher: ' + str(self.searcher))
  499         s.append('buffer (last 100 chars): ' + str(self.buffer)[-100:])
  500         s.append('before (last 100 chars): ' + str(self.before)[-100:])
  501         s.append('after: ' + str(self.after))
  502         s.append('match: ' + str(self.match))
  503         s.append('match_index: ' + str(self.match_index))
  504         s.append('exitstatus: ' + str(self.exitstatus))
  505         s.append('flag_eof: ' + str(self.flag_eof))
  506         s.append('pid: ' + str(self.pid))
  507         s.append('child_fd: ' + str(self.child_fd))
  508         s.append('closed: ' + str(self.closed))
  509         s.append('timeout: ' + str(self.timeout))
  510         s.append('delimiter: ' + str(self.delimiter))
  511         s.append('logfile: ' + str(self.logfile))
  512         s.append('logfile_read: ' + str(self.logfile_read))
  513         s.append('logfile_send: ' + str(self.logfile_send))
  514         s.append('maxread: ' + str(self.maxread))
  515         s.append('ignorecase: ' + str(self.ignorecase))
  516         s.append('searchwindowsize: ' + str(self.searchwindowsize))
  517         s.append('delaybeforesend: ' + str(self.delaybeforesend))
  518         s.append('delayafterclose: ' + str(self.delayafterclose))
  519         s.append('delayafterterminate: ' + str(self.delayafterterminate))
  520         return '\n'.join(s)
  521 
  522     def _spawn(self, command, args=None):
  523 
  524         """This starts the given command in a child process. This does all the
  525         fork/exec type of stuff for a pty. This is called by __init__. If args
  526         is empty then command will be parsed (split on spaces) and args will be
  527         set to parsed arguments. """
  528 
  529         # The pid and child_fd of this object get set by this method.
  530         # Note that it is difficult for this method to fail.
  531         # You cannot detect if the child process cannot start.
  532         # So the only way you can tell if the child process started
  533         # or not is to try to read from the file descriptor. If you get
  534         # EOF immediately then it means that the child is already dead.
  535         # That may not necessarily be bad because you may haved spawned a child
  536         # that performs some task; creates no stdout output; and then dies.
  537 
  538         # If command is an int type then it may represent a file descriptor.
  539         if type(command) == type(0):
  540             raise ExceptionPexpect('Command is an int type. If this is a file descriptor then maybe you want to use fdpexpect.fdspawn which takes an existing file descriptor instead of a command string.')
  541 
  542         # Avoids dangerous default
  543         if args is None:
  544             args = []
  545         if type(args) != type([]):
  546             raise TypeError('The argument, args, must be a list.')
  547 
  548         if args == []:
  549             self.args = split_command_line(command)
  550             self.command = self.args[0]
  551         else:
  552             self.args = args[:] # work with a copy
  553             self.args.insert(0, command)
  554             self.command = command
  555 
  556         command_with_path = which(self.command)
  557         if command_with_path is None:
  558             raise ExceptionPexpect('The command was not found or was not executable: %s.' % self.command)
  559         self.command = command_with_path
  560         self.args[0] = self.command
  561 
  562         self.name = '<' + ' '.join(self.args) + '>'
  563 
  564         assert self.pid is None, 'The pid member should be None.'
  565         assert self.command is not None, 'The command member should not be None.'
  566 
  567         if self.use_native_pty_fork:
  568             try:
  569                 self.pid, self.child_fd = pty.fork()
  570             except OSError as e:
  571                 raise ExceptionPexpect('Error! pty.fork() failed: ' + str(e))
  572         else: # Use internal __fork_pty
  573             self.pid, self.child_fd = self.__fork_pty()
  574 
  575         if self.pid == 0: # Child
  576             try:
  577                 self.child_fd = sys.stdout.fileno() # used by setwinsize()
  578                 self.setwinsize(24, 80)
  579             except:
  580                 # Some platforms do not like setwinsize (Cygwin).
  581                 # This will cause problem when running applications that
  582                 # are very picky about window size.
  583                 # This is a serious limitation, but not a show stopper.
  584                 pass
  585             # Do not allow child to inherit open file descriptors from parent.
  586             max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
  587             for i in range(3, max_fd):
  588                 try:
  589                     os.close(i)
  590                 except OSError:
  591                     pass
  592 
  593             # I don't know why this works, but ignoring SIGHUP fixes a
  594             # problem when trying to start a Java daemon with sudo
  595             # (specifically, Tomcat).
  596             signal.signal(signal.SIGHUP, signal.SIG_IGN)
  597 
  598             if self.cwd is not None:
  599                 os.chdir(self.cwd)
  600             if self.env is None:
  601                 os.execv(self.command, self.args)
  602             else:
  603                 os.execvpe(self.command, self.args, self.env)
  604 
  605         # Parent
  606         self.terminated = False
  607         self.closed = False
  608 
  609     def __fork_pty(self):
  610 
  611         """This implements a substitute for the forkpty system call. This
  612         should be more portable than the pty.fork() function. Specifically,
  613         this should work on Solaris.
  614 
  615         Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to
  616         resolve the issue with Python's pty.fork() not supporting Solaris,
  617         particularly ssh. Based on patch to posixmodule.c authored by Noah
  618         Spurrier::
  619 
  620             http://mail.python.org/pipermail/python-dev/2003-May/035281.html
  621 
  622         """
  623 
  624         parent_fd, child_fd = os.openpty()
  625         if parent_fd < 0 or child_fd < 0:
  626             raise ExceptionPexpect("Error! Could not open pty with os.openpty().")
  627 
  628         pid = os.fork()
  629         if pid < 0:
  630             raise ExceptionPexpect("Error! Failed os.fork().")
  631         elif pid == 0:
  632             # Child.
  633             os.close(parent_fd)
  634             self.__pty_make_controlling_tty(child_fd)
  635 
  636             os.dup2(child_fd, 0)
  637             os.dup2(child_fd, 1)
  638             os.dup2(child_fd, 2)
  639 
  640             if child_fd > 2:
  641                 os.close(child_fd)
  642         else:
  643             # Parent.
  644             os.close(child_fd)
  645 
  646         return pid, parent_fd
  647 
  648     def __pty_make_controlling_tty(self, tty_fd):
  649 
  650         """This makes the pseudo-terminal the controlling tty. This should be
  651         more portable than the pty.fork() function. Specifically, this should
  652         work on Solaris. """
  653 
  654         child_name = os.ttyname(tty_fd)
  655 
  656         # Disconnect from controlling tty if still connected.
  657         fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
  658         if fd >= 0:
  659             os.close(fd)
  660 
  661         os.setsid()
  662 
  663         # Verify we are disconnected from controlling tty
  664         try:
  665             fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
  666             if fd >= 0:
  667                 os.close(fd)
  668                 raise ExceptionPexpect("Error! We are not disconnected from a controlling tty.")
  669         except:
  670             # Good! We are disconnected from a controlling tty.
  671             pass
  672 
  673         # Verify we can open child pty.
  674         fd = os.open(child_name, os.O_RDWR)
  675         if fd < 0:
  676             raise ExceptionPexpect("Error! Could not open child pty, " + child_name)
  677         else:
  678             os.close(fd)
  679 
  680         # Verify we now have a controlling tty.
  681         fd = os.open("/dev/tty", os.O_WRONLY)
  682         if fd < 0:
  683             raise ExceptionPexpect("Error! Could not open controlling tty, /dev/tty")
  684         else:
  685             os.close(fd)
  686 
  687     def fileno(self):   # File-like object.
  688 
  689         """This returns the file descriptor of the pty for the child.
  690         """
  691 
  692         return self.child_fd
  693 
  694     def close(self, force=True):   # File-like object.
  695 
  696         """This closes the connection with the child application. Note that
  697         calling close() more than once is valid. This emulates standard Python
  698         behavior with files. Set force to True if you want to make sure that
  699         the child is terminated (SIGKILL is sent if the child ignores SIGHUP
  700         and SIGINT). """
  701 
  702         if not self.closed:
  703             self.flush()
  704             os.close(self.child_fd)
  705             time.sleep(self.delayafterclose) # Give kernel time to update process status.
  706             if self.isalive():
  707                 if not self.terminate(force):
  708                     raise ExceptionPexpect('close() could not terminate the child using terminate()')
  709             self.child_fd = -1
  710             self.closed = True
  711             #self.pid = None
  712 
  713     def flush(self):   # File-like object.
  714 
  715         """This does nothing. It is here to support the interface for a
  716         File-like object. """
  717 
  718         pass
  719 
  720     def isatty(self):   # File-like object.
  721 
  722         """This returns True if the file descriptor is open and connected to a
  723         tty(-like) device, else False. """
  724 
  725         return os.isatty(self.child_fd)
  726 
  727     def waitnoecho(self, timeout=-1):
  728 
  729         """This waits until the terminal ECHO flag is set False. This returns
  730         True if the echo mode is off. This returns False if the ECHO flag was
  731         not set False before the timeout. This can be used to detect when the
  732         child is waiting for a password. Usually a child application will turn
  733         off echo mode when it is waiting for the user to enter a password. For
  734         example, instead of expecting the "password:" prompt you can wait for
  735         the child to set ECHO off::
  736 
  737             p = pexpect.spawn ('ssh user@example.com')
  738             p.waitnoecho()
  739             p.sendline(mypassword)
  740 
  741         If timeout is None then this method to block forever until ECHO flag is
  742         False.
  743 
  744         """
  745 
  746         if timeout == -1:
  747             timeout = self.timeout
  748         if timeout is not None:
  749             end_time = time.time() + timeout
  750         while True:
  751             if not self.getecho():
  752                 return True
  753             if timeout < 0 and timeout is not None:
  754                 return False
  755             if timeout is not None:
  756                 timeout = end_time - time.time()
  757             time.sleep(0.1)
  758 
  759     def getecho(self):
  760 
  761         """This returns the terminal echo mode. This returns True if echo is
  762         on or False if echo is off. Child applications that are expecting you
  763         to enter a password often set ECHO False. See waitnoecho(). """
  764 
  765         attr = termios.tcgetattr(self.child_fd)
  766         if attr[3] & termios.ECHO:
  767             return True
  768         return False
  769 
  770     def setecho(self, state):
  771 
  772         """This sets the terminal echo mode on or off. Note that anything the
  773         child sent before the echo will be lost, so you should be sure that
  774         your input buffer is empty before you call setecho(). For example, the
  775         following will work as expected::
  776 
  777             p = pexpect.spawn('cat')
  778             p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
  779             p.expect (['1234'])
  780             p.expect (['1234'])
  781             p.setecho(False) # Turn off tty echo
  782             p.sendline ('abcd') # We will set this only once (echoed by cat).
  783             p.sendline ('wxyz') # We will set this only once (echoed by cat)
  784             p.expect (['abcd'])
  785             p.expect (['wxyz'])
  786 
  787         The following WILL NOT WORK because the lines sent before the setecho
  788         will be lost::
  789 
  790             p = pexpect.spawn('cat')
  791             p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
  792             p.setecho(False) # Turn off tty echo
  793             p.sendline ('abcd') # We will set this only once (echoed by cat).
  794             p.sendline ('wxyz') # We will set this only once (echoed by cat)
  795             p.expect (['1234'])
  796             p.expect (['1234'])
  797             p.expect (['abcd'])
  798             p.expect (['wxyz'])
  799         """
  800 
  801         attr = termios.tcgetattr(self.child_fd)
  802         if state:
  803             attr[3] = attr[3] | termios.ECHO
  804         else:
  805             attr[3] = attr[3] & ~termios.ECHO
  806         # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent
  807         # and blocked on some platforms. TCSADRAIN is probably ideal if it worked.
  808         termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
  809 
  810     def read_nonblocking(self, size=1, timeout=-1):
  811 
  812         """This reads at most size characters from the child application. It
  813         includes a timeout. If the read does not complete within the timeout
  814         period then a TIMEOUT exception is raised. If the end of file is read
  815         then an EOF exception will be raised. If a log file was set using
  816         setlog() then all data will also be written to the log file.
  817 
  818         If timeout is None then the read may block indefinitely. If timeout is -1
  819         then the self.timeout value is used. If timeout is 0 then the child is
  820         polled and if there was no data immediately ready then this will raise
  821         a TIMEOUT exception.
  822 
  823         The timeout refers only to the amount of time to read at least one
  824         character. This is not effected by the 'size' parameter, so if you call
  825         read_nonblocking(size=100, timeout=30) and only one character is
  826         available right away then one character will be returned immediately.
  827         It will not wait for 30 seconds for another 99 characters to come in.
  828 
  829         This is a wrapper around os.read(). It uses select.select() to
  830         implement the timeout. """
  831 
  832         if self.closed:
  833             raise ValueError('I/O operation on closed file in read_nonblocking().')
  834 
  835         if timeout == -1:
  836             timeout = self.timeout
  837 
  838         # Note that some systems such as Solaris do not give an EOF when
  839         # the child dies. In fact, you can still try to read
  840         # from the child_fd -- it will block forever or until TIMEOUT.
  841         # For this case, I test isalive() before doing any reading.
  842         # If isalive() is false, then I pretend that this is the same as EOF.
  843         if not self.isalive():
  844             r, w, e = self.__select([self.child_fd], [], [], 0) # timeout of 0 means "poll"
  845             if not r:
  846                 self.flag_eof = True
  847                 raise EOF('End Of File (EOF) in read_nonblocking(). Braindead platform.')
  848         elif self.__irix_hack:
  849             # This is a hack for Irix. It seems that Irix requires a long delay before checking isalive.
  850             # This adds a 2 second delay, but only when the child is terminated.
  851             r, w, e = self.__select([self.child_fd], [], [], 2)
  852             if not r and not self.isalive():
  853                 self.flag_eof = True
  854                 raise EOF('End Of File (EOF) in read_nonblocking(). Pokey platform.')
  855 
  856         r, w, e = self.__select([self.child_fd], [], [], timeout)
  857 
  858         if not r:
  859             if not self.isalive():
  860                 # Some platforms, such as Irix, will claim that their processes are alive;
  861                 # then timeout on the select; and then finally admit that they are not alive.
  862                 self.flag_eof = True
  863                 raise EOF('End of File (EOF) in read_nonblocking(). Very pokey platform.')
  864             else:
  865                 raise TIMEOUT('Timeout exceeded in read_nonblocking().')
  866 
  867         if self.child_fd in r:
  868             try:
  869                 s = os.read(self.child_fd, size)
  870             except OSError as e: # Linux does this
  871                 self.flag_eof = True
  872                 raise EOF('End Of File (EOF) in read_nonblocking(). Exception style platform.')
  873             if s == '': # BSD style
  874                 self.flag_eof = True
  875                 raise EOF('End Of File (EOF) in read_nonblocking(). Empty string style platform.')
  876 
  877             if self.logfile is not None:
  878                 self.logfile.write(s)
  879                 self.logfile.flush()
  880             if self.logfile_read is not None:
  881                 self.logfile_read.write(s)
  882                 self.logfile_read.flush()
  883 
  884             return s
  885 
  886         raise ExceptionPexpect('Reached an unexpected state in read_nonblocking().')
  887 
  888     def read(self, size=-1):   # File-like object.
  889 
  890         """This reads at most "size" bytes from the file (less if the read hits
  891         EOF before obtaining size bytes). If the size argument is negative or
  892         omitted, read all data until EOF is reached. The bytes are returned as
  893         a string object. An empty string is returned when EOF is encountered
  894         immediately. """
  895 
  896         if size == 0:
  897             return ''
  898         if size < 0:
  899             self.expect(self.delimiter) # delimiter default is EOF
  900             return self.before
  901 
  902         # I could have done this more directly by not using expect(), but
  903         # I deliberately decided to couple read() to expect() so that
  904         # I would catch any bugs early and ensure consistant behavior.
  905         # It's a little less efficient, but there is less for me to
  906         # worry about if I have to later modify read() or expect().
  907         # Note, it's OK if size==-1 in the regex. That just means it
  908         # will never match anything in which case we stop only on EOF.
  909         cre = re.compile('.{%d}' % size, re.DOTALL)
  910         index = self.expect([cre, self.delimiter]) # delimiter default is EOF
  911         if index == 0:
  912             return self.after ### self.before should be ''. Should I assert this?
  913         return self.before
  914 
  915     def readline(self, size=-1):    # File-like object.
  916 
  917         """This reads and returns one entire line. A trailing newline is kept
  918         in the string, but may be absent when a file ends with an incomplete
  919         line. Note: This readline() looks for a \\r\\n pair even on UNIX
  920         because this is what the pseudo tty device returns. So contrary to what
  921         you may expect you will receive the newline as \\r\\n. An empty string
  922         is returned when EOF is hit immediately. Currently, the size argument is
  923         mostly ignored, so this behavior is not standard for a file-like
  924         object. If size is 0 then an empty string is returned. """
  925 
  926         if size == 0:
  927             return ''
  928         index = self.expect(['\r\n', self.delimiter]) # delimiter default is EOF
  929         if index == 0:
  930             return self.before + '\r\n'
  931         else:
  932             return self.before
  933 
  934     def readlines(self, _sizehint=-1):    # File-like object.
  935 
  936         """This reads until EOF using readline() and returns a list containing
  937         the lines thus read. The optional "sizehint" argument is ignored. """
  938 
  939         lines = []
  940         while True:
  941             line = self.readline()
  942             if not line:
  943                 break
  944             lines.append(line)
  945         return lines
  946 
  947     def write(self, s):   # File-like object.
  948 
  949         """This is similar to send() except that there is no return value.
  950         """
  951 
  952         self.send(s)
  953 
  954     def writelines(self, sequence):   # File-like object.
  955 
  956         """This calls write() for each element in the sequence. The sequence
  957         can be any iterable object producing strings, typically a list of
  958         strings. This does not add line separators There is no return value.
  959         """
  960 
  961         for s in sequence:
  962             self.write(s)
  963 
  964     def send(self, s):
  965 
  966         """This sends a string to the child process. This returns the number of
  967         bytes written. If a log file was set then the data is also written to
  968         the log. """
  969 
  970         time.sleep(self.delaybeforesend)
  971         if self.logfile is not None:
  972             self.logfile.write(s)
  973             self.logfile.flush()
  974         if self.logfile_send is not None:
  975             self.logfile_send.write(s)
  976             self.logfile_send.flush()
  977         c = os.write(self.child_fd, s.encode('utf-8'))
  978         return c
  979 
  980     def sendline(self, s=''):
  981 
  982         """This is like send(), but it adds a line feed (os.linesep). This
  983         returns the number of bytes written. """
  984 
  985         n = self.send(s)
  986         n = n + self.send(os.linesep)
  987         return n
  988 
  989     def sendcontrol(self, char):
  990 
  991         """This sends a control character to the child such as Ctrl-C or
  992         Ctrl-D. For example, to send a Ctrl-G (ASCII 7)::
  993 
  994             child.sendcontrol('g')
  995 
  996         See also, sendintr() and sendeof().
  997         """
  998 
  999         char = char.lower()
 1000         a = ord(char)
 1001         if a >= 97 and a <= 122:
 1002             a = a - ord('a') + 1
 1003             return self.send(chr(a))
 1004         d = {'@':0, '`':0,
 1005             '[':27, '{':27,
 1006             '\\':28, '|':28,
 1007             ']':29, '}': 29,
 1008             '^':30, '~':30,
 1009             '_':31,
 1010             '?':127}
 1011         if char not in d:
 1012             return 0
 1013         return self.send(chr(d[char]))
 1014 
 1015     def sendeof(self):
 1016 
 1017         """This sends an EOF to the child. This sends a character which causes
 1018         the pending parent output buffer to be sent to the waiting child
 1019         program without waiting for end-of-line. If it is the first character
 1020         of the line, the read() in the user program returns 0, which signifies
 1021         end-of-file. This means to work as expected a sendeof() has to be
 1022         called at the beginning of a line. This method does not send a newline.
 1023         It is the responsibility of the caller to ensure the eof is sent at the
 1024         beginning of a line. """
 1025 
 1026         ### Hmmm... how do I send an EOF?
 1027         ###C  if ((m = write(pty, *buf, p - *buf)) < 0)
 1028         ###C      return (errno == EWOULDBLOCK) ? n : -1;
 1029         #fd = sys.stdin.fileno()
 1030         #old = termios.tcgetattr(fd) # remember current state
 1031         #attr = termios.tcgetattr(fd)
 1032         #attr[3] = attr[3] | termios.ICANON # ICANON must be set to recognize EOF
 1033         #try: # use try/finally to ensure state gets restored
 1034         #    termios.tcsetattr(fd, termios.TCSADRAIN, attr)
 1035         #    if hasattr(termios, 'CEOF'):
 1036         #        os.write (self.child_fd, '%c' % termios.CEOF)
 1037         #    else:
 1038         #        # Silly platform does not define CEOF so assume CTRL-D
 1039         #        os.write (self.child_fd, '%c' % 4)
 1040         #finally: # restore state
 1041         #    termios.tcsetattr(fd, termios.TCSADRAIN, old)
 1042         if hasattr(termios, 'VEOF'):
 1043             char = termios.tcgetattr(self.child_fd)[6][termios.VEOF]
 1044         else:
 1045             # platform does not define VEOF so assume CTRL-D
 1046             char = chr(4)
 1047         self.send(char)
 1048 
 1049     def sendintr(self):
 1050 
 1051         """This sends a SIGINT to the child. It does not require
 1052         the SIGINT to be the first character on a line. """
 1053 
 1054         if hasattr(termios, 'VINTR'):
 1055             char = termios.tcgetattr(self.child_fd)[6][termios.VINTR]
 1056         else:
 1057             # platform does not define VINTR so assume CTRL-C
 1058             char = chr(3)
 1059         self.send(char)
 1060 
 1061     def eof(self):
 1062 
 1063         """This returns True if the EOF exception was ever raised.
 1064         """
 1065 
 1066         return self.flag_eof
 1067 
 1068     def terminate(self, force=False):
 1069 
 1070         """This forces a child process to terminate. It starts nicely with
 1071         SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
 1072         returns True if the child was terminated. This returns False if the
 1073         child could not be terminated. """
 1074 
 1075         if not self.isalive():
 1076             return True
 1077         try:
 1078             self.kill(signal.SIGHUP)
 1079             time.sleep(self.delayafterterminate)
 1080             if not self.isalive():
 1081                 return True
 1082             self.kill(signal.SIGCONT)
 1083             time.sleep(self.delayafterterminate)
 1084             if not self.isalive():
 1085                 return True
 1086             self.kill(signal.SIGINT)
 1087             time.sleep(self.delayafterterminate)
 1088             if not self.isalive():
 1089                 return True
 1090             if force:
 1091                 self.kill(signal.SIGKILL)
 1092                 time.sleep(self.delayafterterminate)
 1093                 if not self.isalive():
 1094                     return True
 1095                 else:
 1096                     return False
 1097             return False
 1098         except OSError as e:
 1099             # I think there are kernel timing issues that sometimes cause
 1100             # this to happen. I think isalive() reports True, but the
 1101             # process is dead to the kernel.
 1102             # Make one last attempt to see if the kernel is up to date.
 1103             time.sleep(self.delayafterterminate)
 1104             if not self.isalive():
 1105                 return True
 1106             else:
 1107                 return False
 1108 
 1109     def wait(self):
 1110 
 1111         """This waits until the child exits. This is a blocking call. This will
 1112         not read any data from the child, so this will block forever if the
 1113         child has unread output and has terminated. In other words, the child
 1114         may have printed output then called exit(); but, technically, the child
 1115         is still alive until its output is read. """
 1116 
 1117         if self.isalive():
 1118             pid, status = os.waitpid(self.pid, 0)
 1119         else:
 1120             raise ExceptionPexpect('Cannot wait for dead child process.')
 1121         self.exitstatus = os.WEXITSTATUS(status)
 1122         if os.WIFEXITED(status):
 1123             self.status = status
 1124             self.exitstatus = os.WEXITSTATUS(status)
 1125             self.signalstatus = None
 1126             self.terminated = True
 1127         elif os.WIFSIGNALED(status):
 1128             self.status = status
 1129             self.exitstatus = None
 1130             self.signalstatus = os.WTERMSIG(status)
 1131             self.terminated = True
 1132         elif os.WIFSTOPPED(status):
 1133             raise ExceptionPexpect('Wait was called for a child process that is stopped. This is not supported. Is some other process attempting job control with our child pid?')
 1134         return self.exitstatus
 1135 
 1136     def isalive(self):
 1137 
 1138         """This tests if the child process is running or not. This is
 1139         non-blocking. If the child was terminated then this will read the
 1140         exitstatus or signalstatus of the child. This returns True if the child
 1141         process appears to be running or False if not. It can take literally
 1142         SECONDS for Solaris to return the right status. """
 1143 
 1144         if self.terminated:
 1145             return False
 1146 
 1147         if self.flag_eof:
 1148             # This is for Linux, which requires the blocking form of waitpid to get
 1149             # status of a defunct process. This is super-lame. The flag_eof would have
 1150             # been set in read_nonblocking(), so this should be safe.
 1151             waitpid_options = 0
 1152         else:
 1153             waitpid_options = os.WNOHANG
 1154 
 1155         try:
 1156             pid, status = os.waitpid(self.pid, waitpid_options)
 1157         except OSError as e: # No child processes
 1158             if e.errno == errno.ECHILD:
 1159                 raise ExceptionPexpect('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
 1160             else:
 1161                 raise e
 1162 
 1163         # I have to do this twice for Solaris. I can't even believe that I figured this out...
 1164         # If waitpid() returns 0 it means that no child process wishes to
 1165         # report, and the value of status is undefined.
 1166         if pid == 0:
 1167             try:
 1168                 pid, status = os.waitpid(self.pid, waitpid_options) ### os.WNOHANG) # Solaris!
 1169             except OSError as e: # This should never happen...
 1170                 if e.errno == errno.ECHILD:
 1171                     raise ExceptionPexpect('isalive() encountered condition that should never happen. There was no child process. Did someone else call waitpid() on our process?')
 1172                 else:
 1173                     raise e
 1174 
 1175             # If pid is still 0 after two calls to waitpid() then
 1176             # the process really is alive. This seems to work on all platforms, except
 1177             # for Irix which seems to require a blocking call on waitpid or select, so I let read_nonblocking
 1178             # take care of this situation(unfortunately, this requires waiting through the timeout).
 1179             if pid == 0:
 1180                 return True
 1181 
 1182         if pid == 0:
 1183             return True
 1184 
 1185         if os.WIFEXITED(status):
 1186             self.status = status
 1187             self.exitstatus = os.WEXITSTATUS(status)
 1188             self.signalstatus = None
 1189             self.terminated = True
 1190         elif os.WIFSIGNALED(status):
 1191             self.status = status
 1192             self.exitstatus = None
 1193             self.signalstatus = os.WTERMSIG(status)
 1194             self.terminated = True
 1195         elif os.WIFSTOPPED(status):
 1196             raise ExceptionPexpect('isalive() encountered condition where child process is stopped. This is not supported. Is some other process attempting job control with our child pid?')
 1197         return False
 1198 
 1199     def kill(self, sig):
 1200 
 1201         """This sends the given signal to the child application. In keeping
 1202         with UNIX tradition it has a misleading name. It does not necessarily
 1203         kill the child unless you send the right signal. """
 1204 
 1205         # Same as os.kill, but the pid is given for you.
 1206         if self.isalive():
 1207             os.kill(self.pid, sig)
 1208 
 1209     def compile_pattern_list(self, patterns):
 1210 
 1211         """This compiles a pattern-string or a list of pattern-strings.
 1212         Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of
 1213         those. Patterns may also be None which results in an empty list (you
 1214         might do this if waiting for an EOF or TIMEOUT condition without
 1215         expecting any pattern).
 1216 
 1217         This is used by expect() when calling expect_list(). Thus expect() is
 1218         nothing more than::
 1219 
 1220              cpl = self.compile_pattern_list(pl)
 1221              return self.expect_list(cpl, timeout)
 1222 
 1223         If you are using expect() within a loop it may be more
 1224         efficient to compile the patterns first and then call expect_list().
 1225         This avoid calls in a loop to compile_pattern_list()::
 1226 
 1227              cpl = self.compile_pattern_list(my_pattern)
 1228              while some_condition:
 1229                 ...
 1230                 i = self.expect_list(clp, timeout)
 1231                 ...
 1232         """
 1233 
 1234         if patterns is None:
 1235             return []
 1236         if type(patterns) is not list:
 1237             patterns = [patterns]
 1238 
 1239         compile_flags = re.DOTALL # Allow dot to match \n
 1240         if self.ignorecase:
 1241             compile_flags = compile_flags | re.IGNORECASE
 1242         compiled_pattern_list = []
 1243         for p in patterns:
 1244             if type(p) == str:
 1245                 compiled_pattern_list.append(re.compile(p, compile_flags))
 1246             elif p is EOF:
 1247                 compiled_pattern_list.append(EOF)
 1248             elif p is TIMEOUT:
 1249                 compiled_pattern_list.append(TIMEOUT)
 1250             elif type(p) is type(re.compile('')):
 1251                 compiled_pattern_list.append(p)
 1252             else:
 1253                 raise TypeError('Argument must be one of StringTypes, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)))
 1254 
 1255         return compiled_pattern_list
 1256 
 1257     def expect(self, pattern, timeout=-1, searchwindowsize=None):
 1258 
 1259         """This seeks through the stream until a pattern is matched. The
 1260         pattern is overloaded and may take several types. The pattern can be a
 1261         StringType, EOF, a compiled re, or a list of any of those types.
 1262         Strings will be compiled to re types. This returns the index into the
 1263         pattern list. If the pattern was not a list this returns index 0 on a
 1264         successful match. This may raise exceptions for EOF or TIMEOUT. To
 1265         avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern
 1266         list. That will cause expect to match an EOF or TIMEOUT condition
 1267         instead of raising an exception.
 1268 
 1269         If you pass a list of patterns and more than one matches, the first match
 1270         in the stream is chosen. If more than one pattern matches at that point,
 1271         the leftmost in the pattern list is chosen. For example::
 1272 
 1273             # the input is 'foobar'
 1274             index = p.expect(['bar', 'foo', 'foobar'])
 1275             # returns 1 ('foo') even though 'foobar' is a "better" match
 1276 
 1277         Please note, however, that buffering can affect this behavior, since
 1278         input arrives in unpredictable chunks. For example::
 1279 
 1280             # the input is 'foobar'
 1281             index = p.expect(['foobar', 'foo'])
 1282             # returns 0 ('foobar') if all input is available at once,
 1283             # but returs 1 ('foo') if parts of the final 'bar' arrive late
 1284 
 1285         After a match is found the instance attributes 'before', 'after' and
 1286         'match' will be set. You can see all the data read before the match in
 1287         'before'. You can see the data that was matched in 'after'. The
 1288         re.MatchObject used in the re match will be in 'match'. If an error
 1289         occurred then 'before' will be set to all the data read so far and
 1290         'after' and 'match' will be None.
 1291 
 1292         If timeout is -1 then timeout will be set to the self.timeout value.
 1293 
 1294         A list entry may be EOF or TIMEOUT instead of a string. This will
 1295         catch these exceptions and return the index of the list entry instead
 1296         of raising the exception. The attribute 'after' will be set to the
 1297         exception type. The attribute 'match' will be None. This allows you to
 1298         write code like this::
 1299 
 1300                 index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
 1301                 if index == 0:
 1302                     do_something()
 1303                 elif index == 1:
 1304                     do_something_else()
 1305                 elif index == 2:
 1306                     do_some_other_thing()
 1307                 elif index == 3:
 1308                     do_something_completely_different()
 1309 
 1310         instead of code like this::
 1311 
 1312                 try:
 1313                     index = p.expect(['good', 'bad'])
 1314                     if index == 0:
 1315                         do_something()
 1316                     elif index == 1:
 1317                         do_something_else()
 1318                 except EOF:
 1319                     do_some_other_thing()
 1320                 except TIMEOUT:
 1321                     do_something_completely_different()
 1322 
 1323         These two forms are equivalent. It all depends on what you want. You
 1324         can also just expect the EOF if you are waiting for all output of a
 1325         child to finish. For example::
 1326 
 1327                 p = pexpect.spawn('/bin/ls')
 1328                 p.expect(pexpect.EOF)
 1329                 print p.before
 1330 
 1331         If you are trying to optimize for speed then see expect_list().
 1332         """
 1333 
 1334         compiled_pattern_list = self.compile_pattern_list(pattern)
 1335         return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
 1336 
 1337     def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1):
 1338 
 1339         """This takes a list of compiled regular expressions and returns the
 1340         index into the pattern_list that matched the child output. The list may
 1341         also contain EOF or TIMEOUT (which are not compiled regular
 1342         expressions). This method is similar to the expect() method except that
 1343         expect_list() does not recompile the pattern list on every call. This
 1344         may help if you are trying to optimize for speed, otherwise just use
 1345         the expect() method.  This is called by expect(). If timeout==-1 then
 1346         the self.timeout value is used. If searchwindowsize==-1 then the
 1347         self.searchwindowsize value is used. """
 1348 
 1349         return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
 1350 
 1351     def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1):
 1352 
 1353         """This is similar to expect(), but uses plain string matching instead
 1354         of compiled regular expressions in 'pattern_list'. The 'pattern_list'
 1355         may be a string; a list or other sequence of strings; or TIMEOUT and
 1356         EOF.
 1357 
 1358         This call might be faster than expect() for two reasons: string
 1359         searching is faster than RE matching and it is possible to limit the
 1360         search to just the end of the input buffer.
 1361 
 1362         This method is also useful when you don't want to have to worry about
 1363         escaping regular expression characters that you want to match."""
 1364 
 1365         if type(pattern_list) in str or pattern_list in (TIMEOUT, EOF):
 1366             pattern_list = [pattern_list]
 1367         return self.expect_loop(searcher_string(pattern_list), timeout, searchwindowsize)
 1368 
 1369     def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1):
 1370 
 1371         """This is the common loop used inside expect. The 'searcher' should be
 1372         an instance of searcher_re or searcher_string, which describes how and what
 1373         to search for in the input.
 1374 
 1375         See expect() for other arguments, return value and exceptions. """
 1376 
 1377         self.searcher = searcher
 1378 
 1379         if timeout == -1:
 1380             timeout = self.timeout
 1381         if timeout is not None:
 1382             end_time = time.time() + timeout
 1383         if searchwindowsize == -1:
 1384             searchwindowsize = self.searchwindowsize
 1385 
 1386         try:
 1387             incoming = self.buffer
 1388             freshlen = len(incoming)
 1389             while True: # Keep reading until exception or return.
 1390                 index = searcher.search(incoming, freshlen, searchwindowsize)
 1391                 if index >= 0:
 1392                     self.buffer = incoming[searcher.end : ]
 1393                     self.before = incoming[ : searcher.start]
 1394                     self.after = incoming[searcher.start : searcher.end]
 1395                     self.match = searcher.match
 1396                     self.match_index = index
 1397                     return self.match_index
 1398                 # No match at this point
 1399                 if timeout < 0 and timeout is not None:
 1400                     raise TIMEOUT('Timeout exceeded in expect_any().')
 1401                 # Still have time left, so read more data
 1402                 c = self.read_nonblocking(self.maxread, timeout)
 1403                 freshlen = len(c)
 1404                 time.sleep(0.0001)
 1405                 incoming = incoming + c.decode('utf-8')
 1406                 if timeout is not None:
 1407                     timeout = end_time - time.time()
 1408         except EOF as e:
 1409             self.buffer = ''
 1410             self.before = incoming
 1411             self.after = EOF
 1412             index = searcher.eof_index
 1413             if index >= 0:
 1414                 self.match = EOF
 1415                 self.match_index = index
 1416                 return self.match_index
 1417             else:
 1418                 self.match = None
 1419                 self.match_index = None
 1420                 raise EOF(str(e) + '\n' + str(self))
 1421         except TIMEOUT as e:
 1422             self.buffer = incoming
 1423             self.before = incoming
 1424             self.after = TIMEOUT
 1425             index = searcher.timeout_index
 1426             if index >= 0:
 1427                 self.match = TIMEOUT
 1428                 self.match_index = index
 1429                 return self.match_index
 1430             else:
 1431                 self.match = None
 1432                 self.match_index = None
 1433                 raise TIMEOUT(str(e) + '\n' + str(self))
 1434         except:
 1435             self.before = incoming
 1436             self.after = None
 1437             self.match = None
 1438             self.match_index = None
 1439             raise
 1440 
 1441     def getwinsize(self):
 1442 
 1443         """This returns the terminal window size of the child tty. The return
 1444         value is a tuple of (rows, cols). """
 1445 
 1446         TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912)
 1447         s = struct.pack('HHHH', 0, 0, 0, 0)
 1448         x = fcntl.ioctl(self.fileno(), TIOCGWINSZ, s)
 1449         return struct.unpack('HHHH', x)[0:2]
 1450 
 1451     def setwinsize(self, r, c):
 1452 
 1453         """This sets the terminal window size of the child tty. This will cause
 1454         a SIGWINCH signal to be sent to the child. This does not change the
 1455         physical window size. It changes the size reported to TTY-aware
 1456         applications like vi or curses -- applications that respond to the
 1457         SIGWINCH signal. """
 1458 
 1459         # Check for buggy platforms. Some Python versions on some platforms
 1460         # (notably OSF1 Alpha and RedHat 7.1) truncate the value for
 1461         # termios.TIOCSWINSZ. It is not clear why this happens.
 1462         # These platforms don't seem to handle the signed int very well;
 1463         # yet other platforms like OpenBSD have a large negative value for
 1464         # TIOCSWINSZ and they don't have a truncate problem.
 1465         # Newer versions of Linux have totally different values for TIOCSWINSZ.
 1466         # Note that this fix is a hack.
 1467         TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561)
 1468         if TIOCSWINSZ == 2148037735: # L is not required in Python >= 2.2.
 1469             TIOCSWINSZ = -2146929561 # Same bits, but with sign.
 1470         # Note, assume ws_xpixel and ws_ypixel are zero.
 1471         s = struct.pack('HHHH', r, c, 0, 0)
 1472         fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
 1473 
 1474     def interact(self, escape_character=chr(29), input_filter=None, output_filter=None):
 1475 
 1476         """This gives control of the child process to the interactive user (the
 1477         human at the keyboard). Keystrokes are sent to the child process, and
 1478         the stdout and stderr output of the child process is printed. This
 1479         simply echos the child stdout and child stderr to the real stdout and
 1480         it echos the real stdin to the child stdin. When the user types the
 1481         escape_character this method will stop. The default for
 1482         escape_character is ^]. This should not be confused with ASCII 27 --
 1483         the ESC character. ASCII 29 was chosen for historical merit because
 1484         this is the character used by 'telnet' as the escape character. The
 1485         escape_character will not be sent to the child process.
 1486 
 1487         You may pass in optional input and output filter functions. These
 1488         functions should take a string and return a string. The output_filter
 1489         will be passed all the output from the child process. The input_filter
 1490         will be passed all the keyboard input from the user. The input_filter
 1491         is run BEFORE the check for the escape_character.
 1492 
 1493         Note that if you change the window size of the parent the SIGWINCH
 1494         signal will not be passed through to the child. If you want the child
 1495         window size to change when the parent's window size changes then do
 1496         something like the following example::
 1497 
 1498             import pexpect, struct, fcntl, termios, signal, sys
 1499             def sigwinch_passthrough(sig, data):
 1500                 s = struct.pack("HHHH", 0, 0, 0, 0)
 1501                 a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s))
 1502                 global p
 1503                 p.setwinsize(a[0],a[1])
 1504             p = pexpect.spawn('/bin/bash') # Note this is global and used in sigwinch_passthrough.
 1505             signal.signal(signal.SIGWINCH, sigwinch_passthrough)
 1506             p.interact()
 1507         """
 1508 
 1509         # Flush the buffer.
 1510         self.stdout.write(self.buffer)
 1511         self.stdout.flush()
 1512         self.buffer = ''
 1513         mode = tty.tcgetattr(self.STDIN_FILENO)
 1514         tty.setraw(self.STDIN_FILENO)
 1515         try:
 1516             self.__interact_copy(escape_character, input_filter, output_filter)
 1517         finally:
 1518             tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
 1519 
 1520     def __interact_writen(self, fd, data):
 1521 
 1522         """This is used by the interact() method.
 1523         """
 1524 
 1525         while data != '' and self.isalive():
 1526             n = os.write(fd, data)
 1527             data = data[n:]
 1528 
 1529     def __interact_read(self, fd):
 1530 
 1531         """This is used by the interact() method.
 1532         """
 1533 
 1534         return os.read(fd, 1000)
 1535 
 1536     def __interact_copy(self, escape_character=None, input_filter=None, output_filter=None):
 1537 
 1538         """This is used by the interact() method.
 1539         """
 1540 
 1541         while self.isalive():
 1542             r, w, e = self.__select([self.child_fd, self.STDIN_FILENO], [], [])
 1543             if self.child_fd in r:
 1544                 data = self.__interact_read(self.child_fd)
 1545                 if output_filter:
 1546                     data = output_filter(data)
 1547                 if self.logfile is not None:
 1548                     self.logfile.write(data)
 1549                     self.logfile.flush()
 1550                 os.write(self.STDOUT_FILENO, data)
 1551             if self.STDIN_FILENO in r:
 1552                 data = self.__interact_read(self.STDIN_FILENO)
 1553                 if input_filter:
 1554                     data = input_filter(data)
 1555                 i = data.rfind(escape_character)
 1556                 if i != -1:
 1557                     data = data[:i]
 1558                     self.__interact_writen(self.child_fd, data)
 1559                     break
 1560                 self.__interact_writen(self.child_fd, data)
 1561 
 1562     def __select(self, iwtd, owtd, ewtd, timeout=None):
 1563 
 1564         """This is a wrapper around select.select() that ignores signals. If
 1565         select.select raises a select.error exception and errno is an EINTR
 1566         error then it is ignored. Mainly this is used to ignore sigwinch
 1567         (terminal resize). """
 1568 
 1569         # if select() is interrupted by a signal (errno==EINTR) then
 1570         # we loop back and enter the select() again.
 1571         if timeout is not None:
 1572             end_time = time.time() + timeout
 1573         while True:
 1574             try:
 1575                 return select.select(iwtd, owtd, ewtd, timeout)
 1576             except select.error as e:
 1577                 if e.errno == errno.EINTR:
 1578                     # if we loop back we have to subtract the amount of time we already waited.
 1579                     if timeout is not None:
 1580                         timeout = end_time - time.time()
 1581                         if timeout < 0:
 1582                             return([], [], [])
 1583                 else: # something else caused the select.error, so this really is an exception
 1584                     raise
 1585 
 1586 ##############################################################################
 1587 # The following methods are no longer supported or allowed.
 1588 
 1589     def setmaxread(self, _maxread):
 1590 
 1591         """This method is no longer supported or allowed. I don't like getters
 1592         and setters without a good reason. """
 1593 
 1594         raise ExceptionPexpect('This method is no longer supported or allowed. Just assign a value to the maxread member variable.')
 1595 
 1596     def setlog(self, _fileobject):
 1597 
 1598         """This method is no longer supported or allowed.
 1599         """
 1600 
 1601         raise ExceptionPexpect('This method is no longer supported or allowed. Just assign a value to the logfile member variable.')
 1602 
 1603 ##############################################################################
 1604 # End of spawn class
 1605 ##############################################################################
 1606 
 1607 class searcher_string(object):
 1608 
 1609     """This is a plain string search helper for the spawn.expect_any() method.
 1610 
 1611     Attributes:
 1612 
 1613         eof_index     - index of EOF, or -1
 1614         timeout_index - index of TIMEOUT, or -1
 1615 
 1616     After a successful match by the search() method the following attributes
 1617     are available:
 1618 
 1619         start - index into the buffer, first byte of match
 1620         end   - index into the buffer, first byte after match
 1621         match - the matching string itself
 1622     """
 1623 
 1624     def __init__(self, strings):
 1625 
 1626         """This creates an instance of searcher_string. This argument 'strings'
 1627         may be a list; a sequence of strings; or the EOF or TIMEOUT types. """
 1628 
 1629         self.eof_index = -1
 1630         self.timeout_index = -1
 1631         self._strings = []
 1632         for n, s in zip(list(range(len(strings))), strings):
 1633             if s is EOF:
 1634                 self.eof_index = n
 1635                 continue
 1636             if s is TIMEOUT:
 1637                 self.timeout_index = n
 1638                 continue
 1639             self._strings.append((n, s))
 1640         self.start = self.end = self.match = None
 1641 
 1642     def __str__(self):
 1643 
 1644         """This returns a human-readable string that represents the state of
 1645         the object."""
 1646 
 1647         ss = [(ns[0], '    %d: "%s"' % ns) for ns in self._strings]
 1648         ss.append((-1, 'searcher_string:'))
 1649         if self.eof_index >= 0:
 1650             ss.append((self.eof_index, '    %d: EOF' % self.eof_index))
 1651         if self.timeout_index >= 0:
 1652             ss.append((self.timeout_index, '    %d: TIMEOUT' % self.timeout_index))
 1653         ss.sort()
 1654         ss = zip(*ss)[1]
 1655         return '\n'.join(ss)
 1656 
 1657     def search(self, sbuffer, freshlen, searchwindowsize=None):
 1658 
 1659         """This searches 'sbuffer' for the first occurence of one of the search
 1660         strings.  'freshlen' must indicate the number of bytes at the end of
 1661         'sbuffer' which have not been searched before. It helps to avoid
 1662         searching the same, possibly big, buffer over and over again.
 1663 
 1664         See class spawn for the 'searchwindowsize' argument.
 1665 
 1666         If there is a match this returns the index of that string, and sets
 1667         'start', 'end' and 'match'. Otherwise, this returns -1. """
 1668 
 1669         absurd_match = len(sbuffer)
 1670         first_match = absurd_match
 1671 
 1672         # 'freshlen' helps a lot here. Further optimizations could
 1673         # possibly include:
 1674         #
 1675         # using something like the Boyer-Moore Fast String Searching
 1676         # Algorithm; pre-compiling the search through a list of
 1677         # strings into something that can scan the input once to
 1678         # search for all N strings; realize that if we search for
 1679         # ['bar', 'baz'] and the input is '...foo' we need not bother
 1680         # rescanning until we've read three more bytes.
 1681         #
 1682         # Sadly, I don't know enough about this interesting topic. /grahn
 1683         for index, s in self._strings:
 1684             if searchwindowsize is None:
 1685                 # the match, if any, can only be in the fresh data,
 1686                 # or at the very end of the old data
 1687                 offset = -(freshlen+len(s))
 1688             else:
 1689                 # better obey searchwindowsize
 1690                 offset = -searchwindowsize
 1691             n = sbuffer.find(s, offset)
 1692             if n >= 0 and n < first_match:
 1693                 first_match = n
 1694                 best_index, best_match = index, s
 1695         if first_match == absurd_match:
 1696             return -1
 1697         self.match = best_match
 1698         self.start = first_match
 1699         self.end = self.start + len(self.match)
 1700         return best_index
 1701 
 1702 class searcher_re(object):
 1703 
 1704     """This is regular expression string search helper for the
 1705     spawn.expect_any() method.
 1706 
 1707     Attributes:
 1708 
 1709         eof_index     - index of EOF, or -1
 1710         timeout_index - index of TIMEOUT, or -1
 1711 
 1712     After a successful match by the search() method the following attributes
 1713     are available:
 1714 
 1715         start - index into the buffer, first byte of match
 1716         end   - index into the buffer, first byte after match
 1717         match - the re.match object returned by a succesful re.search
 1718 
 1719     """
 1720 
 1721     def __init__(self, patterns):
 1722 
 1723         """This creates an instance that searches for 'patterns' Where
 1724         'patterns' may be a list or other sequence of compiled regular
 1725         expressions, or the EOF or TIMEOUT types."""
 1726 
 1727         self.eof_index = -1
 1728         self.timeout_index = -1
 1729         self._searches = []
 1730         self.start = self.end = self.match = None
 1731         for n, s in zip(list(range(len(patterns))), patterns):
 1732             if s is EOF:
 1733                 self.eof_index = n
 1734                 continue
 1735             if s is TIMEOUT:
 1736                 self.timeout_index = n
 1737                 continue
 1738             self._searches.append((n, s))
 1739 
 1740     def __str__(self):
 1741 
 1742         """This returns a human-readable string that represents the state of
 1743         the object."""
 1744 
 1745         ss = [(n, '    %d: re.compile("%s")' % (n, str(s.pattern))) for n, s in self._searches]
 1746         ss.append((-1, 'searcher_re:'))
 1747         if self.eof_index >= 0:
 1748             ss.append((self.eof_index, '    %d: EOF' % self.eof_index))
 1749         if self.timeout_index >= 0:
 1750             ss.append((self.timeout_index, '    %d: TIMEOUT' % self.timeout_index))
 1751         ss.sort()
 1752         ss = zip(*ss)[1]
 1753         return '\n'.join(ss)
 1754 
 1755     def search(self, sbuffer, _freshlen, searchwindowsize=None):
 1756 
 1757         """This searches 'sbuffer' for the first occurence of one of the regular
 1758         expressions. 'freshlen' must indicate the number of bytes at the end of
 1759         'sbuffer' which have not been searched before.
 1760 
 1761         See class spawn for the 'searchwindowsize' argument.
 1762 
 1763         If there is a match this returns the index of that string, and sets
 1764         'start', 'end' and 'match'. Otherwise, returns -1."""
 1765 
 1766         absurd_match = len(sbuffer)
 1767         first_match = absurd_match
 1768         # 'freshlen' doesn't help here -- we cannot predict the
 1769         # length of a match, and the re module provides no help.
 1770         if searchwindowsize is None:
 1771             searchstart = 0
 1772         else:
 1773             searchstart = max(0, len(sbuffer)-searchwindowsize)
 1774         for index, s in self._searches:
 1775             match = s.search(sbuffer, searchstart)
 1776             if match is None:
 1777                 continue
 1778             n = match.start()
 1779             if n < first_match:
 1780                 first_match = n
 1781                 the_match = match
 1782                 best_index = index
 1783         if first_match == absurd_match:
 1784             return -1
 1785         self.start = first_match
 1786         self.match = the_match
 1787         self.end = self.match.end()
 1788         return best_index
 1789 
 1790 def which(filename):
 1791 
 1792     """This takes a given filename; tries to find it in the environment path;
 1793     then checks if it is executable. This returns the full path to the filename
 1794     if found and executable. Otherwise this returns None."""
 1795 
 1796     # Special case where filename already contains a path.
 1797     if os.path.dirname(filename) != '':
 1798         if os.access(filename, os.X_OK):
 1799             return filename
 1800 
 1801     if 'PATH' not in os.environ or os.environ['PATH'] == '':
 1802         p = os.defpath
 1803     else:
 1804         p = os.environ['PATH']
 1805 
 1806     pathlist = p.split(os.pathsep)
 1807 
 1808     for path in pathlist:
 1809         f = os.path.join(path, filename)
 1810         if os.access(f, os.X_OK):
 1811             return f
 1812     return None
 1813 
 1814 def split_command_line(command_line):
 1815 
 1816     """This splits a command line into a list of arguments. It splits arguments
 1817     on spaces, but handles embedded quotes, doublequotes, and escaped
 1818     characters. It's impossible to do this with a regular expression, so I
 1819     wrote a little state machine to parse the command line. """
 1820 
 1821     arg_list = []
 1822     arg = ''
 1823 
 1824     # Constants to name the states we can be in.
 1825     state_basic = 0
 1826     state_esc = 1
 1827     state_singlequote = 2
 1828     state_doublequote = 3
 1829     state_whitespace = 4 # The state of consuming whitespace between commands.
 1830     state = state_basic
 1831 
 1832     for c in command_line:
 1833         if state == state_basic or state == state_whitespace:
 1834             if c == '\\': # Escape the next character
 1835                 state = state_esc
 1836             elif c == r"'": # Handle single quote
 1837                 state = state_singlequote
 1838             elif c == r'"': # Handle double quote
 1839                 state = state_doublequote
 1840             elif c.isspace():
 1841                 # Add arg to arg_list if we aren't in the middle of whitespace.
 1842                 if state == state_whitespace:
 1843                     pass # Do nothing.
 1844                 else:
 1845                     arg_list.append(arg)
 1846                     arg = ''
 1847                     state = state_whitespace
 1848             else:
 1849                 arg = arg + c
 1850                 state = state_basic
 1851         elif state == state_esc:
 1852             arg = arg + c
 1853             state = state_basic
 1854         elif state == state_singlequote:
 1855             if c == r"'":
 1856                 state = state_basic
 1857             else:
 1858                 arg = arg + c
 1859         elif state == state_doublequote:
 1860             if c == r'"':
 1861                 state = state_basic
 1862             else:
 1863                 arg = arg + c
 1864 
 1865     if arg != '':
 1866         arg_list.append(arg)
 1867     return arg_list
 1868 
 1869 #
 1870 #
 1871 ###############################################################################
 1872 
 1873 version = 2.5
 1874 
 1875 class ssh_session:
 1876     "Session with extra state including the password to be used."
 1877     # Jason Azze reported:
 1878     # I notice that there is intermittently a very long delay (~30
 1879     # seconds) between "debug2: we sent a publickey packet, wait for reply"
 1880     # and the next debug line, "Authentications that can continue...".
 1881     TIMEOUT = 45
 1882     def __init__(self, user, port, host, password=None, verbose=0):
 1883         self.user = user
 1884         self.host = host
 1885         self.verbose = verbose
 1886         self.password = password
 1887         self.port = port
 1888         self.auth = ""
 1889     def __exec(self, command):
 1890         "Execute a command on the remote host.  Return the output."
 1891         child = spawn(command, timeout=ssh_session.TIMEOUT)
 1892         if self.verbose:
 1893             sys.stderr.write("-> " + command + "\n")
 1894         while True:
 1895             seen = child.expect([EOF,
 1896                                  'assword:',
 1897                                  'continue connecting (yes/no)?',
 1898                                  'Permission denied',
 1899                                  'refused',
 1900                                  'not resolve'])
 1901             if self.verbose:
 1902                 sys.stderr.write("<- " + child.before + "\n")
 1903             if seen == 0:
 1904                 break
 1905             elif seen == 1:
 1906                 if self.verbose:
 1907                     sys.stderr.write("Saw password prompt...\n")
 1908                 if not self.password:
 1909                     self.password = getpass.getpass('Remote password: ')
 1910                 child.sendline(self.password)
 1911             elif seen == 2:
 1912                 if self.verbose:
 1913                     sys.stderr.write("Saw 'continue connecting' prompt...\n")
 1914                 child.sendline("yes")
 1915             elif seen == 3:
 1916                 sys.stderr.write("FAILURE: check your password\n")
 1917                 raise RuntimeError
 1918             elif seen == 4:
 1919                 sys.stderr.write("FAILURE: cannot connect to port " + str(self.port) + "\n")
 1920                 raise RuntimeError
 1921             elif seen == 5:
 1922                 sys.stderr.write("FAILURE: check hostname\n")
 1923                 raise RuntimeError
 1924         # Remote execution will fail noisily if the host key has changed.
 1925         # Pass this message through to the user so there will be a chance
 1926         # to recover.
 1927         if '@@@' in child.before:
 1928             sys.stdout.write(child.before)
 1929             raise RuntimeError
 1930         return child.before
 1931     def ssh(self, command):
 1932         "Execute a command on the remote host, returning its output."
 1933         return self.__exec("ssh%s -p %s -l %s %s \"%s\"" % (self.auth,
 1934                                                             self.port,
 1935                                                             self.user,
 1936                                                             self.host,
 1937                                                             command))
 1938     def scp(self, src, dst):
 1939         "Copy a file to the remote host."
 1940         return self.__exec("scp%s -P %s %s %s@%s:%s" % (self.auth,
 1941                                                         self.port,
 1942                                                         src,
 1943                                                         self.user,
 1944                                                         self.host,
 1945                                                         dst))
 1946     def exists(self, fn):
 1947         "Retrieve file permissions of specified remote file."
 1948         seen = self.ssh("/bin/ls -ld %s" % fn)
 1949         if not seen.strip():
 1950             sys.stderr.write("Remote ls returned empty string, bailing out.\n")
 1951             raise RuntimeError
 1952         if  self.verbose:
 1953             sys.stderr.write("Existence check on %s gave %s\n" % (fn, repr(seen)))
 1954         if seen.find("No such file") > -1:
 1955             return None         # File doesn't exist
 1956         else:
 1957             return seen.split()[0]  # Return permission field of listing.
 1958     def setauth(self, keylist):
 1959         "Set non-default key locations."
 1960         self.auth = " " + " ".join(["-i %s" % x for x in keylist])
 1961 
 1962 class KeyConfig(configparser.RawConfigParser):
 1963     "Store our state about remote keys."
 1964     def __init__(self):
 1965         configparser.RawConfigParser.__init__(self)
 1966         newstyle = os.path.expanduser('~/.config/sshexport.rc')
 1967         oldstyle = os.path.expanduser('~/.ssh/sshexport.rc')
 1968         if os.path.exists(newstyle):
 1969             self.configfile = newstyle
 1970         elif os.path.exists(oldstyle):
 1971             self.configfile = oldstyle
 1972         else:
 1973             self.configfile = None
 1974         if self.configfile:
 1975             if os.stat(self.configfile).st_mode & (stat.S_IROTH | stat.S_IWOTH | stat.S_IRGRP | stat.S_IWGRP):
 1976                 sys.stderr.write("sshexport: %s is not secured!\n" \
 1977                                  % self.configfile)
 1978                 sys.exit(1)
 1979             self.read(self.configfile)
 1980     def save(self):
 1981         if self.configfile:
 1982             self.write(open(self.configfile, "w"))
 1983     def remember(self, session):
 1984         authorized = session.ssh("cat $HOME/.ssh/authorized_keys")
 1985         keydict = {}
 1986         for line in authorized.split("\n"):
 1987             if line.strip():
 1988                 try:
 1989                     (keytype, content, keyid) = line.strip().split()
 1990                     if keyid not in keydict:
 1991                         keydict[keyid] = []
 1992                     keydict[keyid].append(keytype)
 1993                 except ValueError:
 1994                     print("unexpected format in key line '%s'." % repr(line))
 1995         if keydict:
 1996             role = session.user + "@" + session.host
 1997             if not self.has_section(role):
 1998                 self.add_section(role)
 1999             for (keyid, types) in list(keydict.items()):
 2000                 self.set(role, keyid, ",".join(types))
 2001             if session.password is not None:
 2002                 self.set(role, "password", session.password)
 2003             if session.port != 22:
 2004                 self.set("port", str(session.port))
 2005     def forget(self, role):
 2006         for (keyid, _types) in config.items(role):
 2007             if "@" in keyid:
 2008                 self.remove_option(role, keyid)
 2009 
 2010 def die(msg):
 2011     "Die quietly."
 2012     print(msg)
 2013     print("Goodbye.")
 2014     raise SystemExit(1)
 2015 
 2016 def fixperms(session, fn, checkonly=False):
 2017     "Force perms of remote file to user read on, group/other write off."
 2018     perms = session.exists(fn)
 2019     ok = (perms[1] == 'r' and perms[5] == '-' and perms[8] == '-')
 2020     print("Remote %s permissions are %s which is %s." \
 2021           % (fn, perms, ("wrong", "OK")[ok]))
 2022     if not ok:
 2023         print("User read should be on, Group and Other write permissions should be off.")
 2024         if not checkonly:
 2025             print("Correcting permissions...")
 2026             session.ssh("/bin/chmod u+r,g-w,o-w %s" % fn)
 2027     return ok
 2028 
 2029 def forcefile(session, fn, command, checkonly=False):
 2030     "Create file with command if it does not already exist."
 2031     perms = session.exists(fn)
 2032     if perms is None:
 2033         print("Remote %s doesn't exist." % fn)
 2034         if checkonly:
 2035             die("Bailing out...")
 2036         else:
 2037             print("Creating remote %s" % fn)
 2038             session.ssh(command)
 2039             perms = session.exists(fn)
 2040     else:
 2041         print(fn, "already exists.")
 2042     return perms
 2043 
 2044 if __name__ == '__main__':
 2045     # Process options
 2046     try:
 2047         (options, arguments) = getopt.getopt(sys.argv[1:], "rcdhvp:")
 2048     except getopt.GetoptError as e:
 2049         print(e)
 2050         sys.exit(1)
 2051     check = 0
 2052     verbose = 0
 2053     delete = 0
 2054     port = 22
 2055     rotate = 0
 2056 
 2057     # Ignore DSA, it's weak and RSA support is baseline at this point
 2058     supported_keytypes = ("rsa", "ed25519")
 2059 
 2060     for (switch, val) in options:
 2061         if switch == '-r':
 2062             rotate = 1
 2063         elif switch == '-c':
 2064             check = 1
 2065         elif switch == '-d':
 2066             delete = 1
 2067         elif switch == '-p':
 2068             port = val
 2069         elif switch == '-h':
 2070             print(__doc__)
 2071             raise SystemExit(0)
 2072         elif switch == '-v':
 2073             verbose = 1
 2074 
 2075     config = KeyConfig()
 2076 
 2077     # Verify that key pairs are present on the local side
 2078     print("Checking your local configuration...")
 2079     try:
 2080         os.chdir(os.getenv("HOME"))
 2081     except:
 2082         die("Can't find your home directory!")
 2083     if not os.access(".", os.R_OK):
 2084         print("Your home directory is not readable by you. That's weird.")
 2085         die("This probably means $HOME is incorrect.")
 2086     if not os.path.exists(".ssh"):
 2087         print("You have no .ssh directory.")
 2088         if not check:
 2089             print("Creating your .ssh directory.")
 2090             os.mkdir(".ssh")
 2091         else:
 2092             print("Creation of .ssh suppressed.")
 2093     if not os.access(".ssh", os.R_OK):
 2094         print("Your .ssh directory is not readable by you. That's weird.")
 2095         die("This probabably means $HOME is incorrect.")
 2096     try:
 2097         os.chdir(".ssh")
 2098     except:
 2099         die("Can't chdir into your .ssh directory!")
 2100     public_keys = [f for f in ["id_%s.pub" % x for x in supported_keytypes] if os.access(f, os.R_OK)]
 2101     if not public_keys:
 2102         if check:
 2103             supported = " or ".join([x.upper() for x in supported_keytypes])
 2104             print("I don't see any %s key pairs.  You need to generate some.")
 2105             die("Try re-running this script without the check-only option.")
 2106         public_keys = []
 2107         # Some older versions of OpenSSH don't accept ed25519 keys, so
 2108         # we generate and ship an RSA as well.
 2109         for keytype in supported_keytypes:
 2110             print("About to generate a %s key. You will be prompted for a passphrase," % keytype)
 2111             print("Pressing enter at that prompt will create a key with no passphrase")
 2112             os.system("ssh-keygen -t %s -f id_%s" % (keytype, keytype))
 2113             public_keys.append("id_%s.pub" % keytype)
 2114 
 2115     print("I see the following public keys:", ", ".join(public_keys))
 2116     for filename in public_keys:
 2117         private_key = filename[:-4]
 2118         legend = private_key + " corresponding to " + filename + " "
 2119         if os.access(private_key, os.R_OK):
 2120             print(legend + "exists and is readable.")
 2121         else:
 2122             die(legend + "does not exist or is unreadable.")
 2123 
 2124     print("Local configuration looks correct.")
 2125 
 2126     if not arguments and not rotate:
 2127         print("Neither remote host nor -r specified.")
 2128         print(__doc__)
 2129         raise SystemExit(0)
 2130 
 2131     if rotate:
 2132         arguments = config.sections()
 2133 
 2134     # Proceed...
 2135     try:
 2136         keyfile = tempfile.mktemp()
 2137         os.system("cat " + " ".join(public_keys) + " >" + keyfile)
 2138         if verbose:
 2139             print("Public keys consolidated in %s" % keyfile)
 2140 
 2141         for host in arguments:
 2142             login = os.environ.get("LOGNAME") or os.environ.get("USER")
 2143             if "@" in host:
 2144                 (login, host) = host.split("@")
 2145 
 2146             role = login + "@" + host
 2147             if config.has_option(role, "port"):
 2148                 port = config.get(role, "port")
 2149             if config.has_option(role, "password"):
 2150                 password = config.get(role, "password")
 2151             else:
 2152                 password = None
 2153 
 2154             try:
 2155                 # Get session to remote host.
 2156                 print("Starting session to %s..." % role)
 2157                 session = ssh_session(login, port, host,
 2158                                   password=password, verbose=verbose)
 2159                 if not session.exists("$HOME"):
 2160                     print("Remote home directory does not exist, bailing out!")
 2161                     raise RuntimeError
 2162 
 2163                 if delete:
 2164                     session.ssh("rm -fr .ssh")
 2165                     print("Keys for %s@%s have been deleted." % (login, host))
 2166                     config.forget(role)
 2167                 else:
 2168                     # Permissions checks
 2169                     fixperms(session, "$HOME", check)
 2170                     forcefile(session, "$HOME/.ssh", "mkdir $HOME/.ssh", check)
 2171                     fixperms(session, "$HOME/.ssh", check)
 2172 
 2173                     # OK, install keys remotely if they don't exist
 2174                     if not rotate and session.exists("$HOME/.ssh/authorized_keys"):
 2175                         print("authorized_keys already exists on %s, cannot append to it." % host)
 2176                         config.remember(session)
 2177                     elif check:
 2178                         print("Check of %s is complete." % role)
 2179                     else:
 2180                         print("Copying your public keys to", host)
 2181                         session.scp(keyfile, "$HOME/.ssh/authorized_keys")
 2182                         fixperms(session, "$HOME/.ssh/authorized_keys", False)
 2183                         config.remember(session)
 2184                         print("Keys for %s have been installed." % role)
 2185                     config.save()
 2186                 if session.exists('/sbin/restorecon'):
 2187                     print("Root user on a system running selinux, fixing security context of authorized_keys file")
 2188                     session.ssh("/sbin/restorecon $HOME/.ssh/authorized_keys")
 2189             except RuntimeError:
 2190                 pass
 2191 
 2192     finally:
 2193         # It's all over now...
 2194         os.remove(keyfile)
 2195 
 2196 # The following sets edit modes for GNU EMACS
 2197 # Local Variables:
 2198 # mode:python
 2199 # End: